git clone https://git.lucas.co/go_mono.git
draw: substitute Src for Over when the source image is completely opaque.
The two Ops are equivalent, but Src is faster.
Change-Id: I2c73a13755047c224c71fb5af786875f02681de9
Reviewed-on: https://go-review.googlesource.com/8640
Reviewed-by: Rob Pike <r@golang.org>
draw/gen.go | 54 +-
draw/impl.go | 4906 ++++++++++++++-------------------------------------------
draw/scale.go | 7 +
3 files changed, 1234 insertions(+), 3733 deletions(-)
diff --git a/draw/gen.go b/draw/gen.go
index 658270e..1e335e0 100644
--- a/draw/gen.go
+++ b/draw/gen.go
@@ -55,6 +55,7 @@ var (
// should be the fallback pair ("Image", "image.Image").
//
// TODO: add *image.CMYK src type after Go 1.5 is released.
+ // An *image.CMYK is also alwaysOpaque.
dsTypes = []struct{ dType, sType string }{
{"*image.RGBA", "*image.Gray"},
{"*image.RGBA", "*image.NRGBA"},
@@ -72,6 +73,13 @@ var (
"440",
}
ops = []string{"Over", "Src"}
+ // alwaysOpaque are those image.Image implementations that are always
+ // opaque. For these types, Over is equivalent to the faster Src, in the
+ // absence of a source mask.
+ alwaysOpaque = map[string]bool{
+ "*image.Gray": true,
+ "*image.YCbCr": true,
+ }
)
func init() {
@@ -104,6 +112,9 @@ func gen(w *bytes.Buffer, receiver string, codes ...string) {
for _, code := range codes {
for _, t := range dsTypes {
for _, op := range ops {
+ if op == "Over" && alwaysOpaque[t.sType] {
+ continue
+ }
expn(w, code, &data{
dType: t.dType,
sType: t.sType,
@@ -132,6 +143,9 @@ func genKernel(w *bytes.Buffer) {
}
for _, t := range dsTypes {
for _, op := range ops {
+ if op == "Over" && alwaysOpaque[t.sType] {
+ continue
+ }
expn(w, codeKernelTransformLeaf, &data{
dType: t.dType,
sType: t.sType,
@@ -585,7 +599,7 @@ func expnDollar(prefix, dollar, suffix string, d *data) string {
func expnSwitch(op, dType string, expandBoth bool, template string) string {
if op == "" && dType != "anyDType" {
- lines := []string{"switch opts.op() {"}
+ lines := []string{"switch op {"}
for _, op = range ops {
lines = append(lines,
fmt.Sprintf("case %s:", op),
@@ -607,6 +621,14 @@ func expnSwitch(op, dType string, expandBoth bool, template string) string {
fallback, values = "image.Image", sTypesForDType[dType]
}
for _, v := range values {
+ if dType != "" {
+ // v is the sType. Skip those always-opaque sTypes, where Over is
+ // equivalent to Src.
+ if op == "Over" && alwaysOpaque[v] {
+ continue
+ }
+ }
+
if v == fallback {
lines = append(lines, "default:")
} else {
@@ -745,18 +767,22 @@ const (
if adr.Empty() || sr.Empty() {
return
}
+ op := opts.op()
+ if op == Over && opaque(src) { // TODO: also check that opts.SrcMask == nil.
+ op = Src
+ }
// sr is the source pixels. If it extends beyond the src bounds,
// we cannot use the type-specific fast paths, as they access
// the Pix fields directly without bounds checking.
if !sr.In(src.Bounds()) {
- switch opts.op() {
+ switch op {
case Over:
z.scale_Image_Image_Over(dst, dr, adr, src, sr)
case Src:
z.scale_Image_Image_Src(dst, dr, adr, src, sr)
}
} else if _, ok := src.(*image.Uniform); ok {
- Draw(dst, dr, src, src.Bounds().Min, opts.op())
+ Draw(dst, dr, src, src.Bounds().Min, op)
} else {
$switch z.scale_$dTypeRN_$sTypeRN$sratio_$op(dst, dr, adr, src, sr)
}
@@ -769,6 +795,10 @@ const (
if adr.Empty() || sr.Empty() {
return
}
+ op := opts.op()
+ if op == Over && opaque(src) { // TODO: also check that opts.SrcMask == nil.
+ op = Src
+ }
d2s := invert(s2d)
// bias is a translation of the mapping from dst co-ordinates to
// src co-ordinates such that the latter temporarily have
@@ -788,14 +818,14 @@ const (
// we cannot use the type-specific fast paths, as they access
// the Pix fields directly without bounds checking.
if !sr.In(src.Bounds()) {
- switch opts.op() {
+ switch op {
case Over:
z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias)
case Src:
z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias)
}
} else if u, ok := src.(*image.Uniform); ok {
- transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, opts.op())
+ transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
} else {
$switch z.transform_$dTypeRN_$sTypeRN$sratio_$op(dst, dr, adr, &d2s, src, sr, bias)
}
@@ -961,9 +991,13 @@ const (
if adr.Empty() || sr.Empty() {
return
}
+ op := opts.op()
+ if op == Over && opaque(src) { // TODO: also check that opts.SrcMask == nil.
+ op = Src
+ }
if _, ok := src.(*image.Uniform); ok && sr.In(src.Bounds()) {
- Draw(dst, dr, src, src.Bounds().Min, opts.op())
+ Draw(dst, dr, src, src.Bounds().Min, op)
return
}
@@ -998,6 +1032,10 @@ const (
if adr.Empty() || sr.Empty() {
return
}
+ op := opts.op()
+ if op == Over && opaque(src) { // TODO: also check that opts.SrcMask == nil.
+ op = Src
+ }
d2s := invert(s2d)
// bias is a translation of the mapping from dst co-ordinates to
// src co-ordinates such that the latter temporarily have
@@ -1015,7 +1053,7 @@ const (
adr = adr.Sub(dr.Min)
if u, ok := src.(*image.Uniform); ok && sr.In(src.Bounds()) {
- transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, opts.op())
+ transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
return
}
@@ -1032,7 +1070,7 @@ const (
// we cannot use the type-specific fast paths, as they access
// the Pix fields directly without bounds checking.
if !sr.In(src.Bounds()) {
- switch opts.op() {
+ switch op {
case Over:
q.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
case Src:
diff --git a/draw/impl.go b/draw/impl.go
index efe65d2..8fed0bd 100644
--- a/draw/impl.go
+++ b/draw/impl.go
@@ -16,43 +16,32 @@ func (z nnInterpolator) Scale(dst Image, dr image.Rectangle, src image.Image, sr
if adr.Empty() || sr.Empty() {
return
}
+ op := opts.op()
+ if op == Over && opaque(src) { // TODO: also check that opts.SrcMask == nil.
+ op = Src
+ }
// sr is the source pixels. If it extends beyond the src bounds,
// we cannot use the type-specific fast paths, as they access
// the Pix fields directly without bounds checking.
if !sr.In(src.Bounds()) {
- switch opts.op() {
+ switch op {
case Over:
z.scale_Image_Image_Over(dst, dr, adr, src, sr)
case Src:
z.scale_Image_Image_Src(dst, dr, adr, src, sr)
}
} else if _, ok := src.(*image.Uniform); ok {
- Draw(dst, dr, src, src.Bounds().Min, opts.op())
+ Draw(dst, dr, src, src.Bounds().Min, op)
} else {
- switch opts.op() {
+ switch op {
case Over:
switch dst := dst.(type) {
case *image.RGBA:
switch src := src.(type) {
- case *image.Gray:
- z.scale_RGBA_Gray_Over(dst, dr, adr, src, sr)
case *image.NRGBA:
z.scale_RGBA_NRGBA_Over(dst, dr, adr, src, sr)
case *image.RGBA:
z.scale_RGBA_RGBA_Over(dst, dr, adr, src, sr)
- case *image.YCbCr:
- switch src.SubsampleRatio {
- default:
- z.scale_RGBA_Image_Over(dst, dr, adr, src, sr)
- case image.YCbCrSubsampleRatio444:
- z.scale_RGBA_YCbCr444_Over(dst, dr, adr, src, sr)
- case image.YCbCrSubsampleRatio422:
- z.scale_RGBA_YCbCr422_Over(dst, dr, adr, src, sr)
- case image.YCbCrSubsampleRatio420:
- z.scale_RGBA_YCbCr420_Over(dst, dr, adr, src, sr)
- case image.YCbCrSubsampleRatio440:
- z.scale_RGBA_YCbCr440_Over(dst, dr, adr, src, sr)
- }
default:
z.scale_RGBA_Image_Over(dst, dr, adr, src, sr)
}
@@ -105,6 +94,10 @@ func (z nnInterpolator) Transform(dst Image, s2d *f64.Aff3, src image.Image, sr
if adr.Empty() || sr.Empty() {
return
}
+ op := opts.op()
+ if op == Over && opaque(src) { // TODO: also check that opts.SrcMask == nil.
+ op = Src
+ }
d2s := invert(s2d)
// bias is a translation of the mapping from dst co-ordinates to
// src co-ordinates such that the latter temporarily have
@@ -124,39 +117,24 @@ func (z nnInterpolator) Transform(dst Image, s2d *f64.Aff3, src image.Image, sr
// we cannot use the type-specific fast paths, as they access
// the Pix fields directly without bounds checking.
if !sr.In(src.Bounds()) {
- switch opts.op() {
+ switch op {
case Over:
z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias)
case Src:
z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias)
}
} else if u, ok := src.(*image.Uniform); ok {
- transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, opts.op())
+ transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
} else {
- switch opts.op() {
+ switch op {
case Over:
switch dst := dst.(type) {
case *image.RGBA:
switch src := src.(type) {
- case *image.Gray:
- z.transform_RGBA_Gray_Over(dst, dr, adr, &d2s, src, sr, bias)
case *image.NRGBA:
z.transform_RGBA_NRGBA_Over(dst, dr, adr, &d2s, src, sr, bias)
case *image.RGBA:
z.transform_RGBA_RGBA_Over(dst, dr, adr, &d2s, src, sr, bias)
- case *image.YCbCr:
- switch src.SubsampleRatio {
- default:
- z.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias)
- case image.YCbCrSubsampleRatio444:
- z.transform_RGBA_YCbCr444_Over(dst, dr, adr, &d2s, src, sr, bias)
- case image.YCbCrSubsampleRatio422:
- z.transform_RGBA_YCbCr422_Over(dst, dr, adr, &d2s, src, sr, bias)
- case image.YCbCrSubsampleRatio420:
- z.transform_RGBA_YCbCr420_Over(dst, dr, adr, &d2s, src, sr, bias)
- case image.YCbCrSubsampleRatio440:
- z.transform_RGBA_YCbCr440_Over(dst, dr, adr, &d2s, src, sr, bias)
- }
default:
z.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias)
}
@@ -202,27 +180,6 @@ func (z nnInterpolator) Transform(dst Image, s2d *f64.Aff3, src image.Image, sr
}
}
-func (nnInterpolator) scale_RGBA_Gray_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.Gray, sr image.Rectangle) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (2*uint64(dx) + 1) * sw / dw2
- pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx) - src.Rect.Min.X)
- pr := uint32(src.Pix[pi]) * 0x101
- out := uint8(uint32(pr) >> 8)
- dst.Pix[d+0] = out
- dst.Pix[d+1] = out
- dst.Pix[d+2] = out
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
func (nnInterpolator) scale_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.Gray, sr image.Rectangle) {
dw2 := uint64(dr.Dx()) * 2
dh2 := uint64(dr.Dy()) * 2
@@ -336,178 +293,6 @@ func (nnInterpolator) scale_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectang
}
}
-func (nnInterpolator) scale_RGBA_YCbCr444_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (2*uint64(dx) + 1) * sw / dw2
- pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
- pj := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi])<<16 + 1<<15
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pr := (pyy1 + 91881*pcr1) >> 8
- pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pb := (pyy1 + 116130*pcb1) >> 8
- if pr < 0 {
- pr = 0
- } else if pr > 0xffff {
- pr = 0xffff
- }
- if pg < 0 {
- pg = 0
- } else if pg > 0xffff {
- pg = 0xffff
- }
- if pb < 0 {
- pb = 0
- } else if pb > 0xffff {
- pb = 0xffff
- }
- dst.Pix[d+0] = uint8(uint32(pr) >> 8)
- dst.Pix[d+1] = uint8(uint32(pg) >> 8)
- dst.Pix[d+2] = uint8(uint32(pb) >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (nnInterpolator) scale_RGBA_YCbCr422_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (2*uint64(dx) + 1) * sw / dw2
- pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
- pj := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx))/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi])<<16 + 1<<15
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pr := (pyy1 + 91881*pcr1) >> 8
- pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pb := (pyy1 + 116130*pcb1) >> 8
- if pr < 0 {
- pr = 0
- } else if pr > 0xffff {
- pr = 0xffff
- }
- if pg < 0 {
- pg = 0
- } else if pg > 0xffff {
- pg = 0xffff
- }
- if pb < 0 {
- pb = 0
- } else if pb > 0xffff {
- pb = 0xffff
- }
- dst.Pix[d+0] = uint8(uint32(pr) >> 8)
- dst.Pix[d+1] = uint8(uint32(pg) >> 8)
- dst.Pix[d+2] = uint8(uint32(pb) >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (nnInterpolator) scale_RGBA_YCbCr420_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (2*uint64(dx) + 1) * sw / dw2
- pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
- 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)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi])<<16 + 1<<15
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pr := (pyy1 + 91881*pcr1) >> 8
- pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pb := (pyy1 + 116130*pcb1) >> 8
- if pr < 0 {
- pr = 0
- } else if pr > 0xffff {
- pr = 0xffff
- }
- if pg < 0 {
- pg = 0
- } else if pg > 0xffff {
- pg = 0xffff
- }
- if pb < 0 {
- pb = 0
- } else if pb > 0xffff {
- pb = 0xffff
- }
- dst.Pix[d+0] = uint8(uint32(pr) >> 8)
- dst.Pix[d+1] = uint8(uint32(pg) >> 8)
- dst.Pix[d+2] = uint8(uint32(pb) >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (nnInterpolator) scale_RGBA_YCbCr440_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle) {
- dw2 := uint64(dr.Dx()) * 2
- dh2 := uint64(dr.Dy()) * 2
- sw := uint64(sr.Dx())
- sh := uint64(sr.Dy())
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (2*uint64(dy) + 1) * sh / dh2
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (2*uint64(dx) + 1) * sw / dw2
- pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
- pj := ((sr.Min.Y+int(sy))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi])<<16 + 1<<15
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pr := (pyy1 + 91881*pcr1) >> 8
- pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pb := (pyy1 + 116130*pcb1) >> 8
- if pr < 0 {
- pr = 0
- } else if pr > 0xffff {
- pr = 0xffff
- }
- if pg < 0 {
- pg = 0
- } else if pg > 0xffff {
- pg = 0xffff
- }
- if pb < 0 {
- pb = 0
- } else if pb > 0xffff {
- pb = 0xffff
- }
- dst.Pix[d+0] = uint8(uint32(pr) >> 8)
- dst.Pix[d+1] = uint8(uint32(pg) >> 8)
- dst.Pix[d+2] = uint8(uint32(pb) >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
func (nnInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle) {
dw2 := uint64(dr.Dx()) * 2
dh2 := uint64(dr.Dy()) * 2
@@ -760,28 +545,6 @@ func (nnInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle,
}
}
-func (nnInterpolator) transform_RGBA_Gray_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X)
- pr := uint32(src.Pix[pi]) * 0x101
- out := uint8(uint32(pr) >> 8)
- dst.Pix[d+0] = out
- dst.Pix[d+1] = out
- dst.Pix[d+2] = out
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
func (nnInterpolator) transform_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point) {
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
dyf := float64(dr.Min.Y+int(dy)) + 0.5
@@ -900,7 +663,7 @@ func (nnInterpolator) transform_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rec
}
}
-func (nnInterpolator) transform_RGBA_YCbCr444_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
+func (nnInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
dyf := float64(dr.Min.Y+int(dy)) + 0.5
d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
@@ -944,7 +707,7 @@ func (nnInterpolator) transform_RGBA_YCbCr444_Over(dst *image.RGBA, dr, adr imag
}
}
-func (nnInterpolator) transform_RGBA_YCbCr422_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
+func (nnInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
dyf := float64(dr.Min.Y+int(dy)) + 0.5
d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
@@ -988,7 +751,7 @@ func (nnInterpolator) transform_RGBA_YCbCr422_Over(dst *image.RGBA, dr, adr imag
}
}
-func (nnInterpolator) transform_RGBA_YCbCr420_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
+func (nnInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
dyf := float64(dr.Min.Y+int(dy)) + 0.5
d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
@@ -1032,7 +795,7 @@ func (nnInterpolator) transform_RGBA_YCbCr420_Over(dst *image.RGBA, dr, adr imag
}
}
-func (nnInterpolator) transform_RGBA_YCbCr440_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
+func (nnInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
dyf := float64(dr.Min.Y+int(dy)) + 0.5
d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
@@ -1076,7 +839,7 @@ func (nnInterpolator) transform_RGBA_YCbCr440_Over(dst *image.RGBA, dr, adr imag
}
}
-func (nnInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
+func (nnInterpolator) transform_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point) {
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
dyf := float64(dr.Min.Y+int(dy)) + 0.5
d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
@@ -1087,190 +850,14 @@ func (nnInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image
if !(image.Point{sx0, sy0}).In(sr) {
continue
}
- pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- pj := (sy0-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi])<<16 + 1<<15
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pr := (pyy1 + 91881*pcr1) >> 8
- pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pb := (pyy1 + 116130*pcb1) >> 8
- if pr < 0 {
- pr = 0
- } else if pr > 0xffff {
- pr = 0xffff
- }
- if pg < 0 {
- pg = 0
- } else if pg > 0xffff {
- pg = 0xffff
- }
- if pb < 0 {
- pb = 0
- } else if pb > 0xffff {
- pb = 0xffff
- }
- dst.Pix[d+0] = uint8(uint32(pr) >> 8)
- dst.Pix[d+1] = uint8(uint32(pg) >> 8)
- dst.Pix[d+2] = uint8(uint32(pb) >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (nnInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- pj := (sy0-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi])<<16 + 1<<15
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pr := (pyy1 + 91881*pcr1) >> 8
- pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pb := (pyy1 + 116130*pcb1) >> 8
- if pr < 0 {
- pr = 0
- } else if pr > 0xffff {
- pr = 0xffff
- }
- if pg < 0 {
- pg = 0
- } else if pg > 0xffff {
- pg = 0xffff
- }
- if pb < 0 {
- pb = 0
- } else if pb > 0xffff {
- pb = 0xffff
- }
- dst.Pix[d+0] = uint8(uint32(pr) >> 8)
- dst.Pix[d+1] = uint8(uint32(pg) >> 8)
- dst.Pix[d+2] = uint8(uint32(pb) >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (nnInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- pj := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi])<<16 + 1<<15
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pr := (pyy1 + 91881*pcr1) >> 8
- pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pb := (pyy1 + 116130*pcb1) >> 8
- if pr < 0 {
- pr = 0
- } else if pr > 0xffff {
- pr = 0xffff
- }
- if pg < 0 {
- pg = 0
- } else if pg > 0xffff {
- pg = 0xffff
- }
- if pb < 0 {
- pb = 0
- } else if pb > 0xffff {
- pb = 0xffff
- }
- dst.Pix[d+0] = uint8(uint32(pr) >> 8)
- dst.Pix[d+1] = uint8(uint32(pg) >> 8)
- dst.Pix[d+2] = uint8(uint32(pb) >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (nnInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- pj := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi])<<16 + 1<<15
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pr := (pyy1 + 91881*pcr1) >> 8
- pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pb := (pyy1 + 116130*pcb1) >> 8
- if pr < 0 {
- pr = 0
- } else if pr > 0xffff {
- pr = 0xffff
- }
- if pg < 0 {
- pg = 0
- } else if pg > 0xffff {
- pg = 0xffff
- }
- if pb < 0 {
- pb = 0
- } else if pb > 0xffff {
- pb = 0xffff
- }
- dst.Pix[d+0] = uint8(uint32(pr) >> 8)
- dst.Pix[d+1] = uint8(uint32(pg) >> 8)
- dst.Pix[d+2] = uint8(uint32(pb) >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (nnInterpolator) transform_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
- sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y
- if !(image.Point{sx0, sy0}).In(sr) {
- continue
- }
- pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
- dst.Pix[d+0] = uint8(uint32(pr) >> 8)
- dst.Pix[d+1] = uint8(uint32(pg) >> 8)
- dst.Pix[d+2] = uint8(uint32(pb) >> 8)
- dst.Pix[d+3] = uint8(uint32(pa) >> 8)
- }
- }
-}
+ pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
+ dst.Pix[d+0] = uint8(uint32(pr) >> 8)
+ dst.Pix[d+1] = uint8(uint32(pg) >> 8)
+ dst.Pix[d+2] = uint8(uint32(pb) >> 8)
+ dst.Pix[d+3] = uint8(uint32(pa) >> 8)
+ }
+ }
+}
func (nnInterpolator) transform_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point) {
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
@@ -1342,43 +929,32 @@ func (z ablInterpolator) Scale(dst Image, dr image.Rectangle, src image.Image, s
if adr.Empty() || sr.Empty() {
return
}
+ op := opts.op()
+ if op == Over && opaque(src) { // TODO: also check that opts.SrcMask == nil.
+ op = Src
+ }
// sr is the source pixels. If it extends beyond the src bounds,
// we cannot use the type-specific fast paths, as they access
// the Pix fields directly without bounds checking.
if !sr.In(src.Bounds()) {
- switch opts.op() {
+ switch op {
case Over:
z.scale_Image_Image_Over(dst, dr, adr, src, sr)
case Src:
z.scale_Image_Image_Src(dst, dr, adr, src, sr)
}
} else if _, ok := src.(*image.Uniform); ok {
- Draw(dst, dr, src, src.Bounds().Min, opts.op())
+ Draw(dst, dr, src, src.Bounds().Min, op)
} else {
- switch opts.op() {
+ switch op {
case Over:
switch dst := dst.(type) {
case *image.RGBA:
switch src := src.(type) {
- case *image.Gray:
- z.scale_RGBA_Gray_Over(dst, dr, adr, src, sr)
case *image.NRGBA:
z.scale_RGBA_NRGBA_Over(dst, dr, adr, src, sr)
case *image.RGBA:
z.scale_RGBA_RGBA_Over(dst, dr, adr, src, sr)
- case *image.YCbCr:
- switch src.SubsampleRatio {
- default:
- z.scale_RGBA_Image_Over(dst, dr, adr, src, sr)
- case image.YCbCrSubsampleRatio444:
- z.scale_RGBA_YCbCr444_Over(dst, dr, adr, src, sr)
- case image.YCbCrSubsampleRatio422:
- z.scale_RGBA_YCbCr422_Over(dst, dr, adr, src, sr)
- case image.YCbCrSubsampleRatio420:
- z.scale_RGBA_YCbCr420_Over(dst, dr, adr, src, sr)
- case image.YCbCrSubsampleRatio440:
- z.scale_RGBA_YCbCr440_Over(dst, dr, adr, src, sr)
- }
default:
z.scale_RGBA_Image_Over(dst, dr, adr, src, sr)
}
@@ -1431,6 +1007,10 @@ func (z ablInterpolator) Transform(dst Image, s2d *f64.Aff3, src image.Image, sr
if adr.Empty() || sr.Empty() {
return
}
+ op := opts.op()
+ if op == Over && opaque(src) { // TODO: also check that opts.SrcMask == nil.
+ op = Src
+ }
d2s := invert(s2d)
// bias is a translation of the mapping from dst co-ordinates to
// src co-ordinates such that the latter temporarily have
@@ -1450,39 +1030,24 @@ func (z ablInterpolator) Transform(dst Image, s2d *f64.Aff3, src image.Image, sr
// we cannot use the type-specific fast paths, as they access
// the Pix fields directly without bounds checking.
if !sr.In(src.Bounds()) {
- switch opts.op() {
+ switch op {
case Over:
z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias)
case Src:
z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias)
}
} else if u, ok := src.(*image.Uniform); ok {
- transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, opts.op())
+ transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
} else {
- switch opts.op() {
+ switch op {
case Over:
switch dst := dst.(type) {
case *image.RGBA:
switch src := src.(type) {
- case *image.Gray:
- z.transform_RGBA_Gray_Over(dst, dr, adr, &d2s, src, sr, bias)
case *image.NRGBA:
z.transform_RGBA_NRGBA_Over(dst, dr, adr, &d2s, src, sr, bias)
case *image.RGBA:
z.transform_RGBA_RGBA_Over(dst, dr, adr, &d2s, src, sr, bias)
- case *image.YCbCr:
- switch src.SubsampleRatio {
- default:
- z.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias)
- case image.YCbCrSubsampleRatio444:
- z.transform_RGBA_YCbCr444_Over(dst, dr, adr, &d2s, src, sr, bias)
- case image.YCbCrSubsampleRatio422:
- z.transform_RGBA_YCbCr422_Over(dst, dr, adr, &d2s, src, sr, bias)
- case image.YCbCrSubsampleRatio420:
- z.transform_RGBA_YCbCr420_Over(dst, dr, adr, &d2s, src, sr, bias)
- case image.YCbCrSubsampleRatio440:
- z.transform_RGBA_YCbCr440_Over(dst, dr, adr, &d2s, src, sr, bias)
- }
default:
z.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias)
}
@@ -1528,69 +1093,6 @@ func (z ablInterpolator) Transform(dst Image, s2d *f64.Aff3, src image.Image, sr
}
}
-func (ablInterpolator) scale_RGBA_Gray_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.Gray, sr image.Rectangle) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw-1, sh-1
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
-
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
- xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
- xFrac0, xFrac1 = 1, 0
- }
-
- s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- s00ru := uint32(src.Pix[s00i]) * 0x101
- s00r := float64(s00ru)
- s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- s10ru := uint32(src.Pix[s10i]) * 0x101
- s10r := float64(s10ru)
- s10r = xFrac1*s00r + xFrac0*s10r
- s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- s01ru := uint32(src.Pix[s01i]) * 0x101
- s01r := float64(s01ru)
- s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- s11ru := uint32(src.Pix[s11i]) * 0x101
- s11r := float64(s11ru)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11r = yFrac1*s10r + yFrac0*s11r
- out := uint8(uint32(s11r) >> 8)
- dst.Pix[d+0] = out
- dst.Pix[d+1] = out
- dst.Pix[d+2] = out
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
func (ablInterpolator) scale_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.Gray, sr image.Rectangle) {
sw := int32(sr.Dx())
sh := int32(sr.Dy())
@@ -2034,7 +1536,7 @@ func (ablInterpolator) scale_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectan
}
}
-func (ablInterpolator) scale_RGBA_YCbCr444_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle) {
+func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle) {
sw := int32(sr.Dx())
sh := int32(sr.Dy())
yscale := float64(sh) / float64(dr.Dy())
@@ -2206,7 +1708,7 @@ func (ablInterpolator) scale_RGBA_YCbCr444_Over(dst *image.RGBA, dr, adr image.R
}
}
-func (ablInterpolator) scale_RGBA_YCbCr422_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle) {
+func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle) {
sw := int32(sr.Dx())
sh := int32(sr.Dy())
yscale := float64(sh) / float64(dr.Dy())
@@ -2378,7 +1880,7 @@ func (ablInterpolator) scale_RGBA_YCbCr422_Over(dst *image.RGBA, dr, adr image.R
}
}
-func (ablInterpolator) scale_RGBA_YCbCr420_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle) {
+func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle) {
sw := int32(sr.Dx())
sh := int32(sr.Dy())
yscale := float64(sh) / float64(dr.Dy())
@@ -2550,7 +2052,7 @@ func (ablInterpolator) scale_RGBA_YCbCr420_Over(dst *image.RGBA, dr, adr image.R
}
}
-func (ablInterpolator) scale_RGBA_YCbCr440_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle) {
+func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle) {
sw := int32(sr.Dx())
sh := int32(sr.Dy())
yscale := float64(sh) / float64(dr.Dy())
@@ -2722,7 +2224,7 @@ func (ablInterpolator) scale_RGBA_YCbCr440_Over(dst *image.RGBA, dr, adr image.R
}
}
-func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle) {
+func (ablInterpolator) scale_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle) {
sw := int32(sr.Dx())
sh := int32(sr.Dy())
yscale := float64(sh) / float64(dr.Dy())
@@ -2761,140 +2263,47 @@ func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Re
xFrac0, xFrac1 = 1, 0
}
- s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- s00j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i])<<16 + 1<<15
- s00cb1 := int(src.Cb[s00j]) - 128
- s00cr1 := int(src.Cr[s00j]) - 128
- s00ru := (s00yy1 + 91881*s00cr1) >> 8
- s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
- s00bu := (s00yy1 + 116130*s00cb1) >> 8
- if s00ru < 0 {
- s00ru = 0
- } else if s00ru > 0xffff {
- s00ru = 0xffff
- }
- if s00gu < 0 {
- s00gu = 0
- } else if s00gu > 0xffff {
- s00gu = 0xffff
- }
- if s00bu < 0 {
- s00bu = 0
- } else if s00bu > 0xffff {
- s00bu = 0xffff
- }
-
+ s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
s00r := float64(s00ru)
s00g := float64(s00gu)
s00b := float64(s00bu)
- s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- s10j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i])<<16 + 1<<15
- s10cb1 := int(src.Cb[s10j]) - 128
- s10cr1 := int(src.Cr[s10j]) - 128
- s10ru := (s10yy1 + 91881*s10cr1) >> 8
- s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
- s10bu := (s10yy1 + 116130*s10cb1) >> 8
- if s10ru < 0 {
- s10ru = 0
- } else if s10ru > 0xffff {
- s10ru = 0xffff
- }
- if s10gu < 0 {
- s10gu = 0
- } else if s10gu > 0xffff {
- s10gu = 0xffff
- }
- if s10bu < 0 {
- s10bu = 0
- } else if s10bu > 0xffff {
- s10bu = 0xffff
- }
-
+ s00a := float64(s00au)
+ s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
s10r := float64(s10ru)
s10g := float64(s10gu)
s10b := float64(s10bu)
+ s10a := float64(s10au)
s10r = xFrac1*s00r + xFrac0*s10r
s10g = xFrac1*s00g + xFrac0*s10g
s10b = xFrac1*s00b + xFrac0*s10b
- s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- s01j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i])<<16 + 1<<15
- s01cb1 := int(src.Cb[s01j]) - 128
- s01cr1 := int(src.Cr[s01j]) - 128
- s01ru := (s01yy1 + 91881*s01cr1) >> 8
- s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
- s01bu := (s01yy1 + 116130*s01cb1) >> 8
- if s01ru < 0 {
- s01ru = 0
- } else if s01ru > 0xffff {
- s01ru = 0xffff
- }
- if s01gu < 0 {
- s01gu = 0
- } else if s01gu > 0xffff {
- s01gu = 0xffff
- }
- if s01bu < 0 {
- s01bu = 0
- } else if s01bu > 0xffff {
- s01bu = 0xffff
- }
-
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
s01r := float64(s01ru)
s01g := float64(s01gu)
s01b := float64(s01bu)
- s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- s11j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i])<<16 + 1<<15
- s11cb1 := int(src.Cb[s11j]) - 128
- s11cr1 := int(src.Cr[s11j]) - 128
- s11ru := (s11yy1 + 91881*s11cr1) >> 8
- s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
- s11bu := (s11yy1 + 116130*s11cb1) >> 8
- if s11ru < 0 {
- s11ru = 0
- } else if s11ru > 0xffff {
- s11ru = 0xffff
- }
- if s11gu < 0 {
- s11gu = 0
- } else if s11gu > 0xffff {
- s11gu = 0xffff
- }
- if s11bu < 0 {
- s11bu = 0
- } else if s11bu > 0xffff {
- s11bu = 0xffff
- }
-
+ s01a := float64(s01au)
+ s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
s11r := float64(s11ru)
s11g := float64(s11gu)
s11b := float64(s11bu)
+ s11a := float64(s11au)
s11r = xFrac1*s01r + xFrac0*s11r
s11g = xFrac1*s01g + xFrac0*s11g
s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
s11r = yFrac1*s10r + yFrac0*s11r
s11g = yFrac1*s10g + yFrac0*s11g
s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
dst.Pix[d+0] = uint8(uint32(s11r) >> 8)
dst.Pix[d+1] = uint8(uint32(s11g) >> 8)
dst.Pix[d+2] = uint8(uint32(s11b) >> 8)
- dst.Pix[d+3] = 0xff
+ dst.Pix[d+3] = uint8(uint32(s11a) >> 8)
}
}
}
-func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle) {
+func (ablInterpolator) scale_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle) {
sw := int32(sr.Dx())
sh := int32(sr.Dy())
yscale := float64(sh) / float64(dr.Dy())
@@ -2933,145 +2342,54 @@ func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Re
xFrac0, xFrac1 = 1, 0
}
- s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- s00j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i])<<16 + 1<<15
- s00cb1 := int(src.Cb[s00j]) - 128
- s00cr1 := int(src.Cr[s00j]) - 128
- s00ru := (s00yy1 + 91881*s00cr1) >> 8
- s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
- s00bu := (s00yy1 + 116130*s00cb1) >> 8
- if s00ru < 0 {
- s00ru = 0
- } else if s00ru > 0xffff {
- s00ru = 0xffff
- }
- if s00gu < 0 {
- s00gu = 0
- } else if s00gu > 0xffff {
- s00gu = 0xffff
- }
- if s00bu < 0 {
- s00bu = 0
- } else if s00bu > 0xffff {
- s00bu = 0xffff
- }
-
+ s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
s00r := float64(s00ru)
s00g := float64(s00gu)
s00b := float64(s00bu)
- s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- s10j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i])<<16 + 1<<15
- s10cb1 := int(src.Cb[s10j]) - 128
- s10cr1 := int(src.Cr[s10j]) - 128
- s10ru := (s10yy1 + 91881*s10cr1) >> 8
- s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
- s10bu := (s10yy1 + 116130*s10cb1) >> 8
- if s10ru < 0 {
- s10ru = 0
- } else if s10ru > 0xffff {
- s10ru = 0xffff
- }
- if s10gu < 0 {
- s10gu = 0
- } else if s10gu > 0xffff {
- s10gu = 0xffff
- }
- if s10bu < 0 {
- s10bu = 0
- } else if s10bu > 0xffff {
- s10bu = 0xffff
- }
-
+ s00a := float64(s00au)
+ s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
s10r := float64(s10ru)
s10g := float64(s10gu)
s10b := float64(s10bu)
+ s10a := float64(s10au)
s10r = xFrac1*s00r + xFrac0*s10r
s10g = xFrac1*s00g + xFrac0*s10g
s10b = xFrac1*s00b + xFrac0*s10b
- s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- s01j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i])<<16 + 1<<15
- s01cb1 := int(src.Cb[s01j]) - 128
- s01cr1 := int(src.Cr[s01j]) - 128
- s01ru := (s01yy1 + 91881*s01cr1) >> 8
- s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
- s01bu := (s01yy1 + 116130*s01cb1) >> 8
- if s01ru < 0 {
- s01ru = 0
- } else if s01ru > 0xffff {
- s01ru = 0xffff
- }
- if s01gu < 0 {
- s01gu = 0
- } else if s01gu > 0xffff {
- s01gu = 0xffff
- }
- if s01bu < 0 {
- s01bu = 0
- } else if s01bu > 0xffff {
- s01bu = 0xffff
- }
-
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
s01r := float64(s01ru)
s01g := float64(s01gu)
s01b := float64(s01bu)
- s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- s11j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i])<<16 + 1<<15
- s11cb1 := int(src.Cb[s11j]) - 128
- s11cr1 := int(src.Cr[s11j]) - 128
- s11ru := (s11yy1 + 91881*s11cr1) >> 8
- s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
- s11bu := (s11yy1 + 116130*s11cb1) >> 8
- if s11ru < 0 {
- s11ru = 0
- } else if s11ru > 0xffff {
- s11ru = 0xffff
- }
- if s11gu < 0 {
- s11gu = 0
- } else if s11gu > 0xffff {
- s11gu = 0xffff
- }
- if s11bu < 0 {
- s11bu = 0
- } else if s11bu > 0xffff {
- s11bu = 0xffff
- }
-
+ s01a := float64(s01au)
+ s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
s11r := float64(s11ru)
s11g := float64(s11gu)
s11b := float64(s11bu)
+ s11a := float64(s11au)
s11r = xFrac1*s01r + xFrac0*s11r
s11g = xFrac1*s01g + xFrac0*s11g
s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
s11r = yFrac1*s10r + yFrac0*s11r
s11g = yFrac1*s10g + yFrac0*s11g
s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
dst.Pix[d+0] = uint8(uint32(s11r) >> 8)
dst.Pix[d+1] = uint8(uint32(s11g) >> 8)
dst.Pix[d+2] = uint8(uint32(s11b) >> 8)
- dst.Pix[d+3] = 0xff
+ dst.Pix[d+3] = uint8(uint32(s11a) >> 8)
}
}
}
-func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle) {
+func (ablInterpolator) scale_Image_Image_Over(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle) {
sw := int32(sr.Dx())
sh := int32(sr.Dy())
yscale := float64(sh) / float64(dr.Dy())
xscale := float64(sw) / float64(dr.Dx())
swMinus1, shMinus1 := sw-1, sh-1
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
sy := (float64(dy)+0.5)*yscale - 0.5
@@ -3089,9 +2407,8 @@ func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Re
sy0, sy1 = shMinus1, shMinus1
yFrac0, yFrac1 = 1, 0
}
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
sx := (float64(dx)+0.5)*xscale - 0.5
sx0 := int32(sx)
xFrac0 := sx - float64(sx0)
@@ -3105,145 +2422,55 @@ func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Re
xFrac0, xFrac1 = 1, 0
}
- s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- 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)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i])<<16 + 1<<15
- s00cb1 := int(src.Cb[s00j]) - 128
- s00cr1 := int(src.Cr[s00j]) - 128
- s00ru := (s00yy1 + 91881*s00cr1) >> 8
- s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
- s00bu := (s00yy1 + 116130*s00cb1) >> 8
- if s00ru < 0 {
- s00ru = 0
- } else if s00ru > 0xffff {
- s00ru = 0xffff
- }
- if s00gu < 0 {
- s00gu = 0
- } else if s00gu > 0xffff {
- s00gu = 0xffff
- }
- if s00bu < 0 {
- s00bu = 0
- } else if s00bu > 0xffff {
- s00bu = 0xffff
- }
-
+ s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
s00r := float64(s00ru)
s00g := float64(s00gu)
s00b := float64(s00bu)
- s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- 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)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i])<<16 + 1<<15
- s10cb1 := int(src.Cb[s10j]) - 128
- s10cr1 := int(src.Cr[s10j]) - 128
- s10ru := (s10yy1 + 91881*s10cr1) >> 8
- s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
- s10bu := (s10yy1 + 116130*s10cb1) >> 8
- if s10ru < 0 {
- s10ru = 0
- } else if s10ru > 0xffff {
- s10ru = 0xffff
- }
- if s10gu < 0 {
- s10gu = 0
- } else if s10gu > 0xffff {
- s10gu = 0xffff
- }
- if s10bu < 0 {
- s10bu = 0
- } else if s10bu > 0xffff {
- s10bu = 0xffff
- }
-
+ s00a := float64(s00au)
+ s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
s10r := float64(s10ru)
s10g := float64(s10gu)
s10b := float64(s10bu)
+ s10a := float64(s10au)
s10r = xFrac1*s00r + xFrac0*s10r
s10g = xFrac1*s00g + xFrac0*s10g
s10b = xFrac1*s00b + xFrac0*s10b
- s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- 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)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i])<<16 + 1<<15
- s01cb1 := int(src.Cb[s01j]) - 128
- s01cr1 := int(src.Cr[s01j]) - 128
- s01ru := (s01yy1 + 91881*s01cr1) >> 8
- s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
- s01bu := (s01yy1 + 116130*s01cb1) >> 8
- if s01ru < 0 {
- s01ru = 0
- } else if s01ru > 0xffff {
- s01ru = 0xffff
- }
- if s01gu < 0 {
- s01gu = 0
- } else if s01gu > 0xffff {
- s01gu = 0xffff
- }
- if s01bu < 0 {
- s01bu = 0
- } else if s01bu > 0xffff {
- s01bu = 0xffff
- }
-
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
s01r := float64(s01ru)
s01g := float64(s01gu)
s01b := float64(s01bu)
- s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- 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)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i])<<16 + 1<<15
- s11cb1 := int(src.Cb[s11j]) - 128
- s11cr1 := int(src.Cr[s11j]) - 128
- s11ru := (s11yy1 + 91881*s11cr1) >> 8
- s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
- s11bu := (s11yy1 + 116130*s11cb1) >> 8
- if s11ru < 0 {
- s11ru = 0
- } else if s11ru > 0xffff {
- s11ru = 0xffff
- }
- if s11gu < 0 {
- s11gu = 0
- } else if s11gu > 0xffff {
- s11gu = 0xffff
- }
- if s11bu < 0 {
- s11bu = 0
- } else if s11bu > 0xffff {
- s11bu = 0xffff
- }
-
+ s01a := float64(s01au)
+ s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
s11r := float64(s11ru)
s11g := float64(s11gu)
s11b := float64(s11bu)
+ s11a := float64(s11au)
s11r = xFrac1*s01r + xFrac0*s11r
s11g = xFrac1*s01g + xFrac0*s11g
s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
s11r = yFrac1*s10r + yFrac0*s11r
s11g = yFrac1*s10g + yFrac0*s11g
s11b = yFrac1*s10b + yFrac0*s11b
- dst.Pix[d+0] = uint8(uint32(s11r) >> 8)
- dst.Pix[d+1] = uint8(uint32(s11g) >> 8)
- dst.Pix[d+2] = uint8(uint32(s11b) >> 8)
- dst.Pix[d+3] = 0xff
+ s11a = yFrac1*s10a + yFrac0*s11a
+ dstColorRGBA64.R = uint16(s11r)
+ dstColorRGBA64.G = uint16(s11g)
+ dstColorRGBA64.B = uint16(s11b)
+ dstColorRGBA64.A = uint16(s11a)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
}
}
}
-func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle) {
+func (ablInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle) {
sw := int32(sr.Dx())
sh := int32(sr.Dy())
yscale := float64(sh) / float64(dr.Dy())
xscale := float64(sw) / float64(dr.Dx())
swMinus1, shMinus1 := sw-1, sh-1
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
sy := (float64(dy)+0.5)*yscale - 0.5
@@ -3261,9 +2488,8 @@ func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Re
sy0, sy1 = shMinus1, shMinus1
yFrac0, yFrac1 = 1, 0
}
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
sx := (float64(dx)+0.5)*xscale - 0.5
sx0 := int32(sx)
xFrac0 := sx - float64(sx0)
@@ -3277,184 +2503,165 @@ func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Re
xFrac0, xFrac1 = 1, 0
}
- s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- s00j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i])<<16 + 1<<15
- s00cb1 := int(src.Cb[s00j]) - 128
- s00cr1 := int(src.Cr[s00j]) - 128
- s00ru := (s00yy1 + 91881*s00cr1) >> 8
- s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
- s00bu := (s00yy1 + 116130*s00cb1) >> 8
- if s00ru < 0 {
- s00ru = 0
- } else if s00ru > 0xffff {
- s00ru = 0xffff
- }
- if s00gu < 0 {
- s00gu = 0
- } else if s00gu > 0xffff {
- s00gu = 0xffff
- }
- if s00bu < 0 {
- s00bu = 0
- } else if s00bu > 0xffff {
- s00bu = 0xffff
- }
-
+ s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
s00r := float64(s00ru)
s00g := float64(s00gu)
s00b := float64(s00bu)
- s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- s10j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i])<<16 + 1<<15
- s10cb1 := int(src.Cb[s10j]) - 128
- s10cr1 := int(src.Cr[s10j]) - 128
- s10ru := (s10yy1 + 91881*s10cr1) >> 8
- s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
- s10bu := (s10yy1 + 116130*s10cb1) >> 8
- if s10ru < 0 {
- s10ru = 0
- } else if s10ru > 0xffff {
- s10ru = 0xffff
- }
- if s10gu < 0 {
- s10gu = 0
- } else if s10gu > 0xffff {
- s10gu = 0xffff
- }
- if s10bu < 0 {
- s10bu = 0
- } else if s10bu > 0xffff {
- s10bu = 0xffff
- }
-
+ s00a := float64(s00au)
+ s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
s10r := float64(s10ru)
s10g := float64(s10gu)
s10b := float64(s10bu)
+ s10a := float64(s10au)
s10r = xFrac1*s00r + xFrac0*s10r
s10g = xFrac1*s00g + xFrac0*s10g
s10b = xFrac1*s00b + xFrac0*s10b
- s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
- s01j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i])<<16 + 1<<15
- s01cb1 := int(src.Cb[s01j]) - 128
- s01cr1 := int(src.Cr[s01j]) - 128
- s01ru := (s01yy1 + 91881*s01cr1) >> 8
- s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
- s01bu := (s01yy1 + 116130*s01cb1) >> 8
- if s01ru < 0 {
- s01ru = 0
- } else if s01ru > 0xffff {
- s01ru = 0xffff
- }
- if s01gu < 0 {
- s01gu = 0
- } else if s01gu > 0xffff {
- s01gu = 0xffff
- }
- if s01bu < 0 {
- s01bu = 0
- } else if s01bu > 0xffff {
- s01bu = 0xffff
- }
-
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
s01r := float64(s01ru)
s01g := float64(s01gu)
s01b := float64(s01bu)
- s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
- s11j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i])<<16 + 1<<15
- s11cb1 := int(src.Cb[s11j]) - 128
- s11cr1 := int(src.Cr[s11j]) - 128
- s11ru := (s11yy1 + 91881*s11cr1) >> 8
- s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
- s11bu := (s11yy1 + 116130*s11cb1) >> 8
- if s11ru < 0 {
- s11ru = 0
- } else if s11ru > 0xffff {
- s11ru = 0xffff
- }
- if s11gu < 0 {
- s11gu = 0
- } else if s11gu > 0xffff {
- s11gu = 0xffff
- }
- if s11bu < 0 {
- s11bu = 0
- } else if s11bu > 0xffff {
- s11bu = 0xffff
- }
-
+ s01a := float64(s01au)
+ s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
s11r := float64(s11ru)
s11g := float64(s11gu)
s11b := float64(s11bu)
+ s11a := float64(s11au)
s11r = xFrac1*s01r + xFrac0*s11r
s11g = xFrac1*s01g + xFrac0*s11g
s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
s11r = yFrac1*s10r + yFrac0*s11r
s11g = yFrac1*s10g + yFrac0*s11g
s11b = yFrac1*s10b + yFrac0*s11b
- dst.Pix[d+0] = uint8(uint32(s11r) >> 8)
- dst.Pix[d+1] = uint8(uint32(s11g) >> 8)
- dst.Pix[d+2] = uint8(uint32(s11b) >> 8)
- dst.Pix[d+3] = 0xff
+ s11a = yFrac1*s10a + yFrac0*s11a
+ dstColorRGBA64.R = uint16(s11r)
+ dstColorRGBA64.G = uint16(s11g)
+ dstColorRGBA64.B = uint16(s11b)
+ dstColorRGBA64.A = uint16(s11a)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
}
}
}
-func (ablInterpolator) scale_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw-1, sh-1
-
+func (ablInterpolator) transform_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point) {
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ sx -= 0.5
+ sx0 := int(sx)
+ xFrac0 := sx - float64(sx0)
+ xFrac1 := 1 - xFrac0
+ sx0 += bias.X
+ sx1 := sx0 + 1
+ if sx0 < sr.Min.X {
+ sx0, sx1 = sr.Min.X, sr.Min.X
+ xFrac0, xFrac1 = 0, 1
+ } else if sx1 >= sr.Max.X {
+ sx0, sx1 = sr.Max.X-1, sr.Max.X-1
+ xFrac0, xFrac1 = 1, 0
+ }
+
+ sy -= 0.5
+ sy0 := int(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy0 += bias.Y
+ sy1 := sy0 + 1
+ if sy0 < sr.Min.Y {
+ sy0, sy1 = sr.Min.Y, sr.Min.Y
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 >= sr.Max.Y {
+ sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X)
+ s00ru := uint32(src.Pix[s00i]) * 0x101
+ s00r := float64(s00ru)
+ s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1 - src.Rect.Min.X)
+ s10ru := uint32(src.Pix[s10i]) * 0x101
+ s10r := float64(s10ru)
+ s10r = xFrac1*s00r + xFrac0*s10r
+ s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X)
+ s01ru := uint32(src.Pix[s01i]) * 0x101
+ s01r := float64(s01ru)
+ s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1 - src.Rect.Min.X)
+ s11ru := uint32(src.Pix[s11i]) * 0x101
+ s11r := float64(s11ru)
+ s11r = xFrac1*s01r + xFrac0*s11r
+ s11r = yFrac1*s10r + yFrac0*s11r
+ out := uint8(uint32(s11r) >> 8)
+ dst.Pix[d+0] = out
+ dst.Pix[d+1] = out
+ dst.Pix[d+2] = out
+ dst.Pix[d+3] = 0xff
+ }
+ }
+}
+func (ablInterpolator) transform_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point) {
+ for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ sx -= 0.5
+ sx0 := int(sx)
xFrac0 := sx - float64(sx0)
xFrac1 := 1 - xFrac0
+ sx0 += bias.X
sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
+ if sx0 < sr.Min.X {
+ sx0, sx1 = sr.Min.X, sr.Min.X
xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
+ } else if sx1 >= sr.Max.X {
+ sx0, sx1 = sr.Max.X-1, sr.Max.X-1
xFrac0, xFrac1 = 1, 0
}
- s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
+ sy -= 0.5
+ sy0 := int(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy0 += bias.Y
+ sy1 := sy0 + 1
+ if sy0 < sr.Min.Y {
+ sy0, sy1 = sr.Min.Y, sr.Min.Y
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 >= sr.Max.Y {
+ sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ s00au := uint32(src.Pix[s00i+3]) * 0x101
+ s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff
+ s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff
+ s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff
s00r := float64(s00ru)
s00g := float64(s00gu)
s00b := float64(s00bu)
s00a := float64(s00au)
- s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
+ s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
+ s10au := uint32(src.Pix[s10i+3]) * 0x101
+ s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff
+ s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff
+ s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff
s10r := float64(s10ru)
s10g := float64(s10gu)
s10b := float64(s10bu)
@@ -3463,12 +2670,20 @@ func (ablInterpolator) scale_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rect
s10g = xFrac1*s00g + xFrac0*s10g
s10b = xFrac1*s00b + xFrac0*s10b
s10a = xFrac1*s00a + xFrac0*s10a
- s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
+ s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ s01au := uint32(src.Pix[s01i+3]) * 0x101
+ s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff
+ s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff
+ s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff
s01r := float64(s01ru)
s01g := float64(s01gu)
s01b := float64(s01bu)
s01a := float64(s01au)
- s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
+ s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
+ s11au := uint32(src.Pix[s11i+3]) * 0x101
+ s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff
+ s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff
+ s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff
s11r := float64(s11ru)
s11g := float64(s11gu)
s11b := float64(s11bu)
@@ -3489,51 +2704,60 @@ func (ablInterpolator) scale_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rect
}
}
-func (ablInterpolator) scale_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw-1, sh-1
-
+func (ablInterpolator) transform_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point) {
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
-
for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
+
+ sx -= 0.5
+ sx0 := int(sx)
xFrac0 := sx - float64(sx0)
xFrac1 := 1 - xFrac0
+ sx0 += bias.X
sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
+ if sx0 < sr.Min.X {
+ sx0, sx1 = sr.Min.X, sr.Min.X
xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
+ } else if sx1 >= sr.Max.X {
+ sx0, sx1 = sr.Max.X-1, sr.Max.X-1
xFrac0, xFrac1 = 1, 0
}
- s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
+ sy -= 0.5
+ sy0 := int(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy0 += bias.Y
+ sy1 := sy0 + 1
+ if sy0 < sr.Min.Y {
+ sy0, sy1 = sr.Min.Y, sr.Min.Y
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 >= sr.Max.Y {
+ sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
+ yFrac0, yFrac1 = 1, 0
+ }
+
+ s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ s00au := uint32(src.Pix[s00i+3]) * 0x101
+ s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff
+ s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff
+ s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff
s00r := float64(s00ru)
s00g := float64(s00gu)
s00b := float64(s00bu)
s00a := float64(s00au)
- s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
+ s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
+ s10au := uint32(src.Pix[s10i+3]) * 0x101
+ s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff
+ s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff
+ s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff
s10r := float64(s10ru)
s10g := float64(s10gu)
s10b := float64(s10bu)
@@ -3542,12 +2766,20 @@ func (ablInterpolator) scale_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Recta
s10g = xFrac1*s00g + xFrac0*s10g
s10b = xFrac1*s00b + xFrac0*s10b
s10a = xFrac1*s00a + xFrac0*s10a
- s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
+ s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ s01au := uint32(src.Pix[s01i+3]) * 0x101
+ s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff
+ s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff
+ s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff
s01r := float64(s01ru)
s01g := float64(s01gu)
s01b := float64(s01bu)
s01a := float64(s01au)
- s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
+ s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
+ s11au := uint32(src.Pix[s11i+3]) * 0x101
+ s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff
+ s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff
+ s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff
s11r := float64(s11ru)
s11g := float64(s11gu)
s11b := float64(s11bu)
@@ -3568,133 +2800,60 @@ func (ablInterpolator) scale_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Recta
}
}
-func (ablInterpolator) scale_Image_Image_Over(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw-1, sh-1
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
-
+func (ablInterpolator) transform_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point) {
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
+ dyf := float64(dr.Min.Y+int(dy)) + 0.5
+ d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ dxf := float64(dr.Min.X+int(dx)) + 0.5
+ sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
+ sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
+ if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
+ continue
+ }
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
+ sx -= 0.5
+ sx0 := int(sx)
xFrac0 := sx - float64(sx0)
xFrac1 := 1 - xFrac0
+ sx0 += bias.X
sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
+ if sx0 < sr.Min.X {
+ sx0, sx1 = sr.Min.X, sr.Min.X
xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
+ } else if sx1 >= sr.Max.X {
+ sx0, sx1 = sr.Max.X-1, sr.Max.X-1
xFrac0, xFrac1 = 1, 0
}
- s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- dstColorRGBA64.R = uint16(s11r)
- dstColorRGBA64.G = uint16(s11g)
- dstColorRGBA64.B = uint16(s11b)
- dstColorRGBA64.A = uint16(s11a)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- }
- }
-}
-
-func (ablInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle) {
- sw := int32(sr.Dx())
- sh := int32(sr.Dy())
- yscale := float64(sh) / float64(dr.Dy())
- xscale := float64(sw) / float64(dr.Dx())
- swMinus1, shMinus1 := sw-1, sh-1
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- sy := (float64(dy)+0.5)*yscale - 0.5
- // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
- // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
- // sx, below.
- sy0 := int32(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy1 := sy0 + 1
- if sy < 0 {
- sy0, sy1 = 0, 0
- yFrac0, yFrac1 = 0, 1
- } else if sy1 > shMinus1 {
- sy0, sy1 = shMinus1, shMinus1
- yFrac0, yFrac1 = 1, 0
- }
-
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- sx := (float64(dx)+0.5)*xscale - 0.5
- sx0 := int32(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx1 := sx0 + 1
- if sx < 0 {
- sx0, sx1 = 0, 0
- xFrac0, xFrac1 = 0, 1
- } else if sx1 > swMinus1 {
- sx0, sx1 = swMinus1, swMinus1
- xFrac0, xFrac1 = 1, 0
+ sy -= 0.5
+ sy0 := int(sy)
+ yFrac0 := sy - float64(sy0)
+ yFrac1 := 1 - yFrac0
+ sy0 += bias.Y
+ sy1 := sy0 + 1
+ if sy0 < sr.Min.Y {
+ sy0, sy1 = sr.Min.Y, sr.Min.Y
+ yFrac0, yFrac1 = 0, 1
+ } else if sy1 >= sr.Max.Y {
+ sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
+ yFrac0, yFrac1 = 1, 0
}
- s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
+ s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ s00ru := uint32(src.Pix[s00i+0]) * 0x101
+ s00gu := uint32(src.Pix[s00i+1]) * 0x101
+ s00bu := uint32(src.Pix[s00i+2]) * 0x101
+ s00au := uint32(src.Pix[s00i+3]) * 0x101
s00r := float64(s00ru)
s00g := float64(s00gu)
s00b := float64(s00bu)
s00a := float64(s00au)
- s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
+ s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
+ s10ru := uint32(src.Pix[s10i+0]) * 0x101
+ s10gu := uint32(src.Pix[s10i+1]) * 0x101
+ s10bu := uint32(src.Pix[s10i+2]) * 0x101
+ s10au := uint32(src.Pix[s10i+3]) * 0x101
s10r := float64(s10ru)
s10g := float64(s10gu)
s10b := float64(s10bu)
@@ -3703,12 +2862,20 @@ func (ablInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle,
s10g = xFrac1*s00g + xFrac0*s10g
s10b = xFrac1*s00b + xFrac0*s10b
s10a = xFrac1*s00a + xFrac0*s10a
- s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
+ s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ s01ru := uint32(src.Pix[s01i+0]) * 0x101
+ s01gu := uint32(src.Pix[s01i+1]) * 0x101
+ s01bu := uint32(src.Pix[s01i+2]) * 0x101
+ s01au := uint32(src.Pix[s01i+3]) * 0x101
s01r := float64(s01ru)
s01g := float64(s01gu)
s01b := float64(s01bu)
s01a := float64(s01au)
- s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
+ s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
+ s11ru := uint32(src.Pix[s11i+0]) * 0x101
+ s11gu := uint32(src.Pix[s11i+1]) * 0x101
+ s11bu := uint32(src.Pix[s11i+2]) * 0x101
+ s11au := uint32(src.Pix[s11i+3]) * 0x101
s11r := float64(s11ru)
s11g := float64(s11gu)
s11b := float64(s11bu)
@@ -3721,16 +2888,15 @@ func (ablInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle,
s11g = yFrac1*s10g + yFrac0*s11g
s11b = yFrac1*s10b + yFrac0*s11b
s11a = yFrac1*s10a + yFrac0*s11a
- dstColorRGBA64.R = uint16(s11r)
- dstColorRGBA64.G = uint16(s11g)
- dstColorRGBA64.B = uint16(s11b)
- dstColorRGBA64.A = uint16(s11a)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
+ dst.Pix[d+0] = uint8(uint32(s11r) >> 8)
+ dst.Pix[d+1] = uint8(uint32(s11g) >> 8)
+ dst.Pix[d+2] = uint8(uint32(s11b) >> 8)
+ dst.Pix[d+3] = uint8(uint32(s11a) >> 8)
}
}
}
-func (ablInterpolator) transform_RGBA_Gray_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point) {
+func (ablInterpolator) transform_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point) {
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
dyf := float64(dr.Min.Y+int(dy)) + 0.5
d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
@@ -3770,31 +2936,63 @@ func (ablInterpolator) transform_RGBA_Gray_Over(dst *image.RGBA, dr, adr image.R
yFrac0, yFrac1 = 1, 0
}
- s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X)
- s00ru := uint32(src.Pix[s00i]) * 0x101
+ s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ s00ru := uint32(src.Pix[s00i+0]) * 0x101
+ s00gu := uint32(src.Pix[s00i+1]) * 0x101
+ s00bu := uint32(src.Pix[s00i+2]) * 0x101
+ s00au := uint32(src.Pix[s00i+3]) * 0x101
s00r := float64(s00ru)
- s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1 - src.Rect.Min.X)
- s10ru := uint32(src.Pix[s10i]) * 0x101
+ s00g := float64(s00gu)
+ s00b := float64(s00bu)
+ s00a := float64(s00au)
+ s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
+ s10ru := uint32(src.Pix[s10i+0]) * 0x101
+ s10gu := uint32(src.Pix[s10i+1]) * 0x101
+ s10bu := uint32(src.Pix[s10i+2]) * 0x101
+ s10au := uint32(src.Pix[s10i+3]) * 0x101
s10r := float64(s10ru)
+ s10g := float64(s10gu)
+ s10b := float64(s10bu)
+ s10a := float64(s10au)
s10r = xFrac1*s00r + xFrac0*s10r
- s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X)
- s01ru := uint32(src.Pix[s01i]) * 0x101
+ s10g = xFrac1*s00g + xFrac0*s10g
+ s10b = xFrac1*s00b + xFrac0*s10b
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
+ s01ru := uint32(src.Pix[s01i+0]) * 0x101
+ s01gu := uint32(src.Pix[s01i+1]) * 0x101
+ s01bu := uint32(src.Pix[s01i+2]) * 0x101
+ s01au := uint32(src.Pix[s01i+3]) * 0x101
s01r := float64(s01ru)
- s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1 - src.Rect.Min.X)
- s11ru := uint32(src.Pix[s11i]) * 0x101
+ s01g := float64(s01gu)
+ s01b := float64(s01bu)
+ s01a := float64(s01au)
+ s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
+ s11ru := uint32(src.Pix[s11i+0]) * 0x101
+ s11gu := uint32(src.Pix[s11i+1]) * 0x101
+ s11bu := uint32(src.Pix[s11i+2]) * 0x101
+ s11au := uint32(src.Pix[s11i+3]) * 0x101
s11r := float64(s11ru)
+ s11g := float64(s11gu)
+ s11b := float64(s11bu)
+ s11a := float64(s11au)
s11r = xFrac1*s01r + xFrac0*s11r
+ s11g = xFrac1*s01g + xFrac0*s11g
+ s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
s11r = yFrac1*s10r + yFrac0*s11r
- out := uint8(uint32(s11r) >> 8)
- dst.Pix[d+0] = out
- dst.Pix[d+1] = out
- dst.Pix[d+2] = out
- dst.Pix[d+3] = 0xff
+ s11g = yFrac1*s10g + yFrac0*s11g
+ s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
+ dst.Pix[d+0] = uint8(uint32(s11r) >> 8)
+ dst.Pix[d+1] = uint8(uint32(s11g) >> 8)
+ dst.Pix[d+2] = uint8(uint32(s11b) >> 8)
+ dst.Pix[d+3] = uint8(uint32(s11a) >> 8)
}
}
}
-func (ablInterpolator) transform_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point) {
+func (ablInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
dyf := float64(dr.Min.Y+int(dy)) + 0.5
d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
@@ -3834,127 +3032,140 @@ func (ablInterpolator) transform_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Re
yFrac0, yFrac1 = 1, 0
}
- s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X)
- s00ru := uint32(src.Pix[s00i]) * 0x101
- s00r := float64(s00ru)
- s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1 - src.Rect.Min.X)
- s10ru := uint32(src.Pix[s10i]) * 0x101
- s10r := float64(s10ru)
- s10r = xFrac1*s00r + xFrac0*s10r
- s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X)
- s01ru := uint32(src.Pix[s01i]) * 0x101
- s01r := float64(s01ru)
- s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1 - src.Rect.Min.X)
- s11ru := uint32(src.Pix[s11i]) * 0x101
- s11r := float64(s11ru)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11r = yFrac1*s10r + yFrac0*s11r
- out := uint8(uint32(s11r) >> 8)
- dst.Pix[d+0] = out
- dst.Pix[d+1] = out
- dst.Pix[d+2] = out
- dst.Pix[d+3] = 0xff
- }
- }
-}
+ s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
+ s00j := (sy0-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
-func (ablInterpolator) transform_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s00yy1 := int(src.Y[s00i])<<16 + 1<<15
+ s00cb1 := int(src.Cb[s00j]) - 128
+ s00cr1 := int(src.Cr[s00j]) - 128
+ s00ru := (s00yy1 + 91881*s00cr1) >> 8
+ s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
+ s00bu := (s00yy1 + 116130*s00cb1) >> 8
+ if s00ru < 0 {
+ s00ru = 0
+ } else if s00ru > 0xffff {
+ s00ru = 0xffff
+ }
+ if s00gu < 0 {
+ s00gu = 0
+ } else if s00gu > 0xffff {
+ s00gu = 0xffff
+ }
+ if s00bu < 0 {
+ s00bu = 0
+ } else if s00bu > 0xffff {
+ s00bu = 0xffff
}
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- s00au := uint32(src.Pix[s00i+3]) * 0x101
- s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff
- s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff
- s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff
s00r := float64(s00ru)
s00g := float64(s00gu)
s00b := float64(s00bu)
- s00a := float64(s00au)
- s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
- s10au := uint32(src.Pix[s10i+3]) * 0x101
- s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff
- s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff
- s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff
+ s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
+ s10j := (sy0-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s10yy1 := int(src.Y[s10i])<<16 + 1<<15
+ s10cb1 := int(src.Cb[s10j]) - 128
+ s10cr1 := int(src.Cr[s10j]) - 128
+ s10ru := (s10yy1 + 91881*s10cr1) >> 8
+ s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
+ s10bu := (s10yy1 + 116130*s10cb1) >> 8
+ if s10ru < 0 {
+ s10ru = 0
+ } else if s10ru > 0xffff {
+ s10ru = 0xffff
+ }
+ if s10gu < 0 {
+ s10gu = 0
+ } else if s10gu > 0xffff {
+ s10gu = 0xffff
+ }
+ if s10bu < 0 {
+ s10bu = 0
+ } else if s10bu > 0xffff {
+ s10bu = 0xffff
+ }
+
s10r := float64(s10ru)
s10g := float64(s10gu)
s10b := float64(s10bu)
- s10a := float64(s10au)
s10r = xFrac1*s00r + xFrac0*s10r
s10g = xFrac1*s00g + xFrac0*s10g
s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- s01au := uint32(src.Pix[s01i+3]) * 0x101
- s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff
- s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff
- s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff
+ s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
+ s01j := (sy1-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s01yy1 := int(src.Y[s01i])<<16 + 1<<15
+ s01cb1 := int(src.Cb[s01j]) - 128
+ s01cr1 := int(src.Cr[s01j]) - 128
+ s01ru := (s01yy1 + 91881*s01cr1) >> 8
+ s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
+ s01bu := (s01yy1 + 116130*s01cb1) >> 8
+ if s01ru < 0 {
+ s01ru = 0
+ } else if s01ru > 0xffff {
+ s01ru = 0xffff
+ }
+ if s01gu < 0 {
+ s01gu = 0
+ } else if s01gu > 0xffff {
+ s01gu = 0xffff
+ }
+ if s01bu < 0 {
+ s01bu = 0
+ } else if s01bu > 0xffff {
+ s01bu = 0xffff
+ }
+
s01r := float64(s01ru)
s01g := float64(s01gu)
s01b := float64(s01bu)
- s01a := float64(s01au)
- s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
- s11au := uint32(src.Pix[s11i+3]) * 0x101
- s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff
- s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff
- s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff
+ s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
+ s11j := (sy1-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s11yy1 := int(src.Y[s11i])<<16 + 1<<15
+ s11cb1 := int(src.Cb[s11j]) - 128
+ s11cr1 := int(src.Cr[s11j]) - 128
+ s11ru := (s11yy1 + 91881*s11cr1) >> 8
+ s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
+ s11bu := (s11yy1 + 116130*s11cb1) >> 8
+ if s11ru < 0 {
+ s11ru = 0
+ } else if s11ru > 0xffff {
+ s11ru = 0xffff
+ }
+ if s11gu < 0 {
+ s11gu = 0
+ } else if s11gu > 0xffff {
+ s11gu = 0xffff
+ }
+ if s11bu < 0 {
+ s11bu = 0
+ } else if s11bu > 0xffff {
+ s11bu = 0xffff
+ }
+
s11r := float64(s11ru)
s11g := float64(s11gu)
s11b := float64(s11bu)
- s11a := float64(s11au)
s11r = xFrac1*s01r + xFrac0*s11r
s11g = xFrac1*s01g + xFrac0*s11g
s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
s11r = yFrac1*s10r + yFrac0*s11r
s11g = yFrac1*s10g + yFrac0*s11g
s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
dst.Pix[d+0] = uint8(uint32(s11r) >> 8)
dst.Pix[d+1] = uint8(uint32(s11g) >> 8)
dst.Pix[d+2] = uint8(uint32(s11b) >> 8)
- dst.Pix[d+3] = uint8(uint32(s11a) >> 8)
+ dst.Pix[d+3] = 0xff
}
}
}
-func (ablInterpolator) transform_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point) {
+func (ablInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
dyf := float64(dr.Min.Y+int(dy)) + 0.5
d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
@@ -3994,255 +3205,140 @@ func (ablInterpolator) transform_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.R
yFrac0, yFrac1 = 1, 0
}
- s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- s00au := uint32(src.Pix[s00i+3]) * 0x101
- s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff
- s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff
- s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff
+ s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
+ s00j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s00yy1 := int(src.Y[s00i])<<16 + 1<<15
+ s00cb1 := int(src.Cb[s00j]) - 128
+ s00cr1 := int(src.Cr[s00j]) - 128
+ s00ru := (s00yy1 + 91881*s00cr1) >> 8
+ s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
+ s00bu := (s00yy1 + 116130*s00cb1) >> 8
+ if s00ru < 0 {
+ s00ru = 0
+ } else if s00ru > 0xffff {
+ s00ru = 0xffff
+ }
+ if s00gu < 0 {
+ s00gu = 0
+ } else if s00gu > 0xffff {
+ s00gu = 0xffff
+ }
+ if s00bu < 0 {
+ s00bu = 0
+ } else if s00bu > 0xffff {
+ s00bu = 0xffff
+ }
+
s00r := float64(s00ru)
s00g := float64(s00gu)
s00b := float64(s00bu)
- s00a := float64(s00au)
- s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
- s10au := uint32(src.Pix[s10i+3]) * 0x101
- s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff
- s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff
- s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff
+ s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
+ s10j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s10yy1 := int(src.Y[s10i])<<16 + 1<<15
+ s10cb1 := int(src.Cb[s10j]) - 128
+ s10cr1 := int(src.Cr[s10j]) - 128
+ s10ru := (s10yy1 + 91881*s10cr1) >> 8
+ s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
+ s10bu := (s10yy1 + 116130*s10cb1) >> 8
+ if s10ru < 0 {
+ s10ru = 0
+ } else if s10ru > 0xffff {
+ s10ru = 0xffff
+ }
+ if s10gu < 0 {
+ s10gu = 0
+ } else if s10gu > 0xffff {
+ s10gu = 0xffff
+ }
+ if s10bu < 0 {
+ s10bu = 0
+ } else if s10bu > 0xffff {
+ s10bu = 0xffff
+ }
+
s10r := float64(s10ru)
s10g := float64(s10gu)
s10b := float64(s10bu)
- s10a := float64(s10au)
s10r = xFrac1*s00r + xFrac0*s10r
s10g = xFrac1*s00g + xFrac0*s10g
s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- s01au := uint32(src.Pix[s01i+3]) * 0x101
- s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff
- s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff
- s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff
+ s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
+ s01j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s01yy1 := int(src.Y[s01i])<<16 + 1<<15
+ s01cb1 := int(src.Cb[s01j]) - 128
+ s01cr1 := int(src.Cr[s01j]) - 128
+ s01ru := (s01yy1 + 91881*s01cr1) >> 8
+ s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
+ s01bu := (s01yy1 + 116130*s01cb1) >> 8
+ if s01ru < 0 {
+ s01ru = 0
+ } else if s01ru > 0xffff {
+ s01ru = 0xffff
+ }
+ if s01gu < 0 {
+ s01gu = 0
+ } else if s01gu > 0xffff {
+ s01gu = 0xffff
+ }
+ if s01bu < 0 {
+ s01bu = 0
+ } else if s01bu > 0xffff {
+ s01bu = 0xffff
+ }
+
s01r := float64(s01ru)
s01g := float64(s01gu)
s01b := float64(s01bu)
- s01a := float64(s01au)
- s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
- s11au := uint32(src.Pix[s11i+3]) * 0x101
- s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff
- s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff
- s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- dst.Pix[d+0] = uint8(uint32(s11r) >> 8)
- dst.Pix[d+1] = uint8(uint32(s11g) >> 8)
- dst.Pix[d+2] = uint8(uint32(s11b) >> 8)
- dst.Pix[d+3] = uint8(uint32(s11a) >> 8)
- }
- }
-}
+ s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
+ s11j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
-func (ablInterpolator) transform_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- s00ru := uint32(src.Pix[s00i+0]) * 0x101
- s00gu := uint32(src.Pix[s00i+1]) * 0x101
- s00bu := uint32(src.Pix[s00i+2]) * 0x101
- s00au := uint32(src.Pix[s00i+3]) * 0x101
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
- s10ru := uint32(src.Pix[s10i+0]) * 0x101
- s10gu := uint32(src.Pix[s10i+1]) * 0x101
- s10bu := uint32(src.Pix[s10i+2]) * 0x101
- s10au := uint32(src.Pix[s10i+3]) * 0x101
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- s01ru := uint32(src.Pix[s01i+0]) * 0x101
- s01gu := uint32(src.Pix[s01i+1]) * 0x101
- s01bu := uint32(src.Pix[s01i+2]) * 0x101
- s01au := uint32(src.Pix[s01i+3]) * 0x101
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
- s11ru := uint32(src.Pix[s11i+0]) * 0x101
- s11gu := uint32(src.Pix[s11i+1]) * 0x101
- s11bu := uint32(src.Pix[s11i+2]) * 0x101
- s11au := uint32(src.Pix[s11i+3]) * 0x101
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- dst.Pix[d+0] = uint8(uint32(s11r) >> 8)
- dst.Pix[d+1] = uint8(uint32(s11g) >> 8)
- dst.Pix[d+2] = uint8(uint32(s11b) >> 8)
- dst.Pix[d+3] = uint8(uint32(s11a) >> 8)
- }
- }
-}
-
-func (ablInterpolator) transform_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ s11yy1 := int(src.Y[s11i])<<16 + 1<<15
+ s11cb1 := int(src.Cb[s11j]) - 128
+ s11cr1 := int(src.Cr[s11j]) - 128
+ s11ru := (s11yy1 + 91881*s11cr1) >> 8
+ s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
+ s11bu := (s11yy1 + 116130*s11cb1) >> 8
+ if s11ru < 0 {
+ s11ru = 0
+ } else if s11ru > 0xffff {
+ s11ru = 0xffff
}
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
+ if s11gu < 0 {
+ s11gu = 0
+ } else if s11gu > 0xffff {
+ s11gu = 0xffff
}
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
+ if s11bu < 0 {
+ s11bu = 0
+ } else if s11bu > 0xffff {
+ s11bu = 0xffff
}
- s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- s00ru := uint32(src.Pix[s00i+0]) * 0x101
- s00gu := uint32(src.Pix[s00i+1]) * 0x101
- s00bu := uint32(src.Pix[s00i+2]) * 0x101
- s00au := uint32(src.Pix[s00i+3]) * 0x101
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
- s10ru := uint32(src.Pix[s10i+0]) * 0x101
- s10gu := uint32(src.Pix[s10i+1]) * 0x101
- s10bu := uint32(src.Pix[s10i+2]) * 0x101
- s10au := uint32(src.Pix[s10i+3]) * 0x101
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
- s01ru := uint32(src.Pix[s01i+0]) * 0x101
- s01gu := uint32(src.Pix[s01i+1]) * 0x101
- s01bu := uint32(src.Pix[s01i+2]) * 0x101
- s01au := uint32(src.Pix[s01i+3]) * 0x101
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
- s11ru := uint32(src.Pix[s11i+0]) * 0x101
- s11gu := uint32(src.Pix[s11i+1]) * 0x101
- s11bu := uint32(src.Pix[s11i+2]) * 0x101
- s11au := uint32(src.Pix[s11i+3]) * 0x101
s11r := float64(s11ru)
s11g := float64(s11gu)
s11b := float64(s11bu)
- s11a := float64(s11au)
s11r = xFrac1*s01r + xFrac0*s11r
s11g = xFrac1*s01g + xFrac0*s11g
s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
s11r = yFrac1*s10r + yFrac0*s11r
s11g = yFrac1*s10g + yFrac0*s11g
s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
dst.Pix[d+0] = uint8(uint32(s11r) >> 8)
dst.Pix[d+1] = uint8(uint32(s11g) >> 8)
dst.Pix[d+2] = uint8(uint32(s11b) >> 8)
- dst.Pix[d+3] = uint8(uint32(s11a) >> 8)
+ dst.Pix[d+3] = 0xff
}
}
}
-func (ablInterpolator) transform_RGBA_YCbCr444_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
+func (ablInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
dyf := float64(dr.Min.Y+int(dy)) + 0.5
d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
@@ -4283,7 +3379,7 @@ func (ablInterpolator) transform_RGBA_YCbCr444_Over(dst *image.RGBA, dr, adr ima
}
s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s00j := (sy0-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
+ s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s00yy1 := int(src.Y[s00i])<<16 + 1<<15
@@ -4312,7 +3408,7 @@ func (ablInterpolator) transform_RGBA_YCbCr444_Over(dst *image.RGBA, dr, adr ima
s00g := float64(s00gu)
s00b := float64(s00bu)
s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s10j := (sy0-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X)
+ s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s10yy1 := int(src.Y[s10i])<<16 + 1<<15
@@ -4344,7 +3440,7 @@ func (ablInterpolator) transform_RGBA_YCbCr444_Over(dst *image.RGBA, dr, adr ima
s10g = xFrac1*s00g + xFrac0*s10g
s10b = xFrac1*s00b + xFrac0*s10b
s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s01j := (sy1-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
+ s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s01yy1 := int(src.Y[s01i])<<16 + 1<<15
@@ -4373,7 +3469,7 @@ func (ablInterpolator) transform_RGBA_YCbCr444_Over(dst *image.RGBA, dr, adr ima
s01g := float64(s01gu)
s01b := float64(s01bu)
s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s11j := (sy1-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X)
+ s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s11yy1 := int(src.Y[s11i])<<16 + 1<<15
@@ -4415,7 +3511,7 @@ func (ablInterpolator) transform_RGBA_YCbCr444_Over(dst *image.RGBA, dr, adr ima
}
}
-func (ablInterpolator) transform_RGBA_YCbCr422_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
+func (ablInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
dyf := float64(dr.Min.Y+int(dy)) + 0.5
d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
@@ -4456,7 +3552,7 @@ func (ablInterpolator) transform_RGBA_YCbCr422_Over(dst *image.RGBA, dr, adr ima
}
s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s00j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
+ s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s00yy1 := int(src.Y[s00i])<<16 + 1<<15
@@ -4485,7 +3581,7 @@ func (ablInterpolator) transform_RGBA_YCbCr422_Over(dst *image.RGBA, dr, adr ima
s00g := float64(s00gu)
s00b := float64(s00bu)
s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s10j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
+ s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s10yy1 := int(src.Y[s10i])<<16 + 1<<15
@@ -4517,7 +3613,7 @@ func (ablInterpolator) transform_RGBA_YCbCr422_Over(dst *image.RGBA, dr, adr ima
s10g = xFrac1*s00g + xFrac0*s10g
s10b = xFrac1*s00b + xFrac0*s10b
s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s01j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
+ s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s01yy1 := int(src.Y[s01i])<<16 + 1<<15
@@ -4546,7 +3642,7 @@ func (ablInterpolator) transform_RGBA_YCbCr422_Over(dst *image.RGBA, dr, adr ima
s01g := float64(s01gu)
s01b := float64(s01bu)
s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s11j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
+ s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X)
// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
s11yy1 := int(src.Y[s11i])<<16 + 1<<15
@@ -4588,7 +3684,7 @@ func (ablInterpolator) transform_RGBA_YCbCr422_Over(dst *image.RGBA, dr, adr ima
}
}
-func (ablInterpolator) transform_RGBA_YCbCr420_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
+func (ablInterpolator) transform_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point) {
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
dyf := float64(dr.Min.Y+int(dy)) + 0.5
d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
@@ -4628,140 +3724,47 @@ func (ablInterpolator) transform_RGBA_YCbCr420_Over(dst *image.RGBA, dr, adr ima
yFrac0, yFrac1 = 1, 0
}
- s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i])<<16 + 1<<15
- s00cb1 := int(src.Cb[s00j]) - 128
- s00cr1 := int(src.Cr[s00j]) - 128
- s00ru := (s00yy1 + 91881*s00cr1) >> 8
- s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
- s00bu := (s00yy1 + 116130*s00cb1) >> 8
- if s00ru < 0 {
- s00ru = 0
- } else if s00ru > 0xffff {
- s00ru = 0xffff
- }
- if s00gu < 0 {
- s00gu = 0
- } else if s00gu > 0xffff {
- s00gu = 0xffff
- }
- if s00bu < 0 {
- s00bu = 0
- } else if s00bu > 0xffff {
- s00bu = 0xffff
- }
-
+ s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
s00r := float64(s00ru)
s00g := float64(s00gu)
s00b := float64(s00bu)
- s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i])<<16 + 1<<15
- s10cb1 := int(src.Cb[s10j]) - 128
- s10cr1 := int(src.Cr[s10j]) - 128
- s10ru := (s10yy1 + 91881*s10cr1) >> 8
- s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
- s10bu := (s10yy1 + 116130*s10cb1) >> 8
- if s10ru < 0 {
- s10ru = 0
- } else if s10ru > 0xffff {
- s10ru = 0xffff
- }
- if s10gu < 0 {
- s10gu = 0
- } else if s10gu > 0xffff {
- s10gu = 0xffff
- }
- if s10bu < 0 {
- s10bu = 0
- } else if s10bu > 0xffff {
- s10bu = 0xffff
- }
-
+ s00a := float64(s00au)
+ s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
s10r := float64(s10ru)
s10g := float64(s10gu)
s10b := float64(s10bu)
+ s10a := float64(s10au)
s10r = xFrac1*s00r + xFrac0*s10r
s10g = xFrac1*s00g + xFrac0*s10g
s10b = xFrac1*s00b + xFrac0*s10b
- s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i])<<16 + 1<<15
- s01cb1 := int(src.Cb[s01j]) - 128
- s01cr1 := int(src.Cr[s01j]) - 128
- s01ru := (s01yy1 + 91881*s01cr1) >> 8
- s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
- s01bu := (s01yy1 + 116130*s01cb1) >> 8
- if s01ru < 0 {
- s01ru = 0
- } else if s01ru > 0xffff {
- s01ru = 0xffff
- }
- if s01gu < 0 {
- s01gu = 0
- } else if s01gu > 0xffff {
- s01gu = 0xffff
- }
- if s01bu < 0 {
- s01bu = 0
- } else if s01bu > 0xffff {
- s01bu = 0xffff
- }
-
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
s01r := float64(s01ru)
s01g := float64(s01gu)
s01b := float64(s01bu)
- s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i])<<16 + 1<<15
- s11cb1 := int(src.Cb[s11j]) - 128
- s11cr1 := int(src.Cr[s11j]) - 128
- s11ru := (s11yy1 + 91881*s11cr1) >> 8
- s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
- s11bu := (s11yy1 + 116130*s11cb1) >> 8
- if s11ru < 0 {
- s11ru = 0
- } else if s11ru > 0xffff {
- s11ru = 0xffff
- }
- if s11gu < 0 {
- s11gu = 0
- } else if s11gu > 0xffff {
- s11gu = 0xffff
- }
- if s11bu < 0 {
- s11bu = 0
- } else if s11bu > 0xffff {
- s11bu = 0xffff
- }
-
+ s01a := float64(s01au)
+ s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
s11r := float64(s11ru)
s11g := float64(s11gu)
s11b := float64(s11bu)
+ s11a := float64(s11au)
s11r = xFrac1*s01r + xFrac0*s11r
s11g = xFrac1*s01g + xFrac0*s11g
s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
s11r = yFrac1*s10r + yFrac0*s11r
s11g = yFrac1*s10g + yFrac0*s11g
s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
dst.Pix[d+0] = uint8(uint32(s11r) >> 8)
dst.Pix[d+1] = uint8(uint32(s11g) >> 8)
dst.Pix[d+2] = uint8(uint32(s11b) >> 8)
- dst.Pix[d+3] = 0xff
+ dst.Pix[d+3] = uint8(uint32(s11a) >> 8)
}
}
}
-func (ablInterpolator) transform_RGBA_YCbCr440_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
+func (ablInterpolator) transform_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point) {
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
dyf := float64(dr.Min.Y+int(dy)) + 0.5
d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
@@ -4801,144 +3804,52 @@ func (ablInterpolator) transform_RGBA_YCbCr440_Over(dst *image.RGBA, dr, adr ima
yFrac0, yFrac1 = 1, 0
}
- s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i])<<16 + 1<<15
- s00cb1 := int(src.Cb[s00j]) - 128
- s00cr1 := int(src.Cr[s00j]) - 128
- s00ru := (s00yy1 + 91881*s00cr1) >> 8
- s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
- s00bu := (s00yy1 + 116130*s00cb1) >> 8
- if s00ru < 0 {
- s00ru = 0
- } else if s00ru > 0xffff {
- s00ru = 0xffff
- }
- if s00gu < 0 {
- s00gu = 0
- } else if s00gu > 0xffff {
- s00gu = 0xffff
- }
- if s00bu < 0 {
- s00bu = 0
- } else if s00bu > 0xffff {
- s00bu = 0xffff
- }
-
+ s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
s00r := float64(s00ru)
s00g := float64(s00gu)
s00b := float64(s00bu)
- s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i])<<16 + 1<<15
- s10cb1 := int(src.Cb[s10j]) - 128
- s10cr1 := int(src.Cr[s10j]) - 128
- s10ru := (s10yy1 + 91881*s10cr1) >> 8
- s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
- s10bu := (s10yy1 + 116130*s10cb1) >> 8
- if s10ru < 0 {
- s10ru = 0
- } else if s10ru > 0xffff {
- s10ru = 0xffff
- }
- if s10gu < 0 {
- s10gu = 0
- } else if s10gu > 0xffff {
- s10gu = 0xffff
- }
- if s10bu < 0 {
- s10bu = 0
- } else if s10bu > 0xffff {
- s10bu = 0xffff
- }
-
+ s00a := float64(s00au)
+ s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
s10r := float64(s10ru)
s10g := float64(s10gu)
s10b := float64(s10bu)
+ s10a := float64(s10au)
s10r = xFrac1*s00r + xFrac0*s10r
s10g = xFrac1*s00g + xFrac0*s10g
s10b = xFrac1*s00b + xFrac0*s10b
- s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i])<<16 + 1<<15
- s01cb1 := int(src.Cb[s01j]) - 128
- s01cr1 := int(src.Cr[s01j]) - 128
- s01ru := (s01yy1 + 91881*s01cr1) >> 8
- s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
- s01bu := (s01yy1 + 116130*s01cb1) >> 8
- if s01ru < 0 {
- s01ru = 0
- } else if s01ru > 0xffff {
- s01ru = 0xffff
- }
- if s01gu < 0 {
- s01gu = 0
- } else if s01gu > 0xffff {
- s01gu = 0xffff
- }
- if s01bu < 0 {
- s01bu = 0
- } else if s01bu > 0xffff {
- s01bu = 0xffff
- }
-
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
s01r := float64(s01ru)
s01g := float64(s01gu)
s01b := float64(s01bu)
- s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i])<<16 + 1<<15
- s11cb1 := int(src.Cb[s11j]) - 128
- s11cr1 := int(src.Cr[s11j]) - 128
- s11ru := (s11yy1 + 91881*s11cr1) >> 8
- s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
- s11bu := (s11yy1 + 116130*s11cb1) >> 8
- if s11ru < 0 {
- s11ru = 0
- } else if s11ru > 0xffff {
- s11ru = 0xffff
- }
- if s11gu < 0 {
- s11gu = 0
- } else if s11gu > 0xffff {
- s11gu = 0xffff
- }
- if s11bu < 0 {
- s11bu = 0
- } else if s11bu > 0xffff {
- s11bu = 0xffff
- }
-
+ s01a := float64(s01au)
+ s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
s11r := float64(s11ru)
s11g := float64(s11gu)
s11b := float64(s11bu)
+ s11a := float64(s11au)
s11r = xFrac1*s01r + xFrac0*s11r
s11g = xFrac1*s01g + xFrac0*s11g
s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
s11r = yFrac1*s10r + yFrac0*s11r
s11g = yFrac1*s10g + yFrac0*s11g
s11b = yFrac1*s10b + yFrac0*s11b
+ s11a = yFrac1*s10a + yFrac0*s11a
dst.Pix[d+0] = uint8(uint32(s11r) >> 8)
dst.Pix[d+1] = uint8(uint32(s11g) >> 8)
dst.Pix[d+2] = uint8(uint32(s11b) >> 8)
- dst.Pix[d+3] = 0xff
+ dst.Pix[d+3] = uint8(uint32(s11a) >> 8)
}
}
}
-func (ablInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
+func (ablInterpolator) transform_Image_Image_Over(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point) {
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
dxf := float64(dr.Min.X+int(dx)) + 0.5
sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
@@ -4974,144 +3885,53 @@ func (ablInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr imag
yFrac0, yFrac1 = 1, 0
}
- s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s00j := (sy0-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i])<<16 + 1<<15
- s00cb1 := int(src.Cb[s00j]) - 128
- s00cr1 := int(src.Cr[s00j]) - 128
- s00ru := (s00yy1 + 91881*s00cr1) >> 8
- s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
- s00bu := (s00yy1 + 116130*s00cb1) >> 8
- if s00ru < 0 {
- s00ru = 0
- } else if s00ru > 0xffff {
- s00ru = 0xffff
- }
- if s00gu < 0 {
- s00gu = 0
- } else if s00gu > 0xffff {
- s00gu = 0xffff
- }
- if s00bu < 0 {
- s00bu = 0
- } else if s00bu > 0xffff {
- s00bu = 0xffff
- }
-
+ s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
s00r := float64(s00ru)
s00g := float64(s00gu)
s00b := float64(s00bu)
- s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s10j := (sy0-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i])<<16 + 1<<15
- s10cb1 := int(src.Cb[s10j]) - 128
- s10cr1 := int(src.Cr[s10j]) - 128
- s10ru := (s10yy1 + 91881*s10cr1) >> 8
- s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
- s10bu := (s10yy1 + 116130*s10cb1) >> 8
- if s10ru < 0 {
- s10ru = 0
- } else if s10ru > 0xffff {
- s10ru = 0xffff
- }
- if s10gu < 0 {
- s10gu = 0
- } else if s10gu > 0xffff {
- s10gu = 0xffff
- }
- if s10bu < 0 {
- s10bu = 0
- } else if s10bu > 0xffff {
- s10bu = 0xffff
- }
-
+ s00a := float64(s00au)
+ s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
s10r := float64(s10ru)
s10g := float64(s10gu)
s10b := float64(s10bu)
+ s10a := float64(s10au)
s10r = xFrac1*s00r + xFrac0*s10r
s10g = xFrac1*s00g + xFrac0*s10g
s10b = xFrac1*s00b + xFrac0*s10b
- s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s01j := (sy1-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i])<<16 + 1<<15
- s01cb1 := int(src.Cb[s01j]) - 128
- s01cr1 := int(src.Cr[s01j]) - 128
- s01ru := (s01yy1 + 91881*s01cr1) >> 8
- s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
- s01bu := (s01yy1 + 116130*s01cb1) >> 8
- if s01ru < 0 {
- s01ru = 0
- } else if s01ru > 0xffff {
- s01ru = 0xffff
- }
- if s01gu < 0 {
- s01gu = 0
- } else if s01gu > 0xffff {
- s01gu = 0xffff
- }
- if s01bu < 0 {
- s01bu = 0
- } else if s01bu > 0xffff {
- s01bu = 0xffff
- }
-
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
s01r := float64(s01ru)
s01g := float64(s01gu)
s01b := float64(s01bu)
- s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s11j := (sy1-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i])<<16 + 1<<15
- s11cb1 := int(src.Cb[s11j]) - 128
- s11cr1 := int(src.Cr[s11j]) - 128
- s11ru := (s11yy1 + 91881*s11cr1) >> 8
- s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
- s11bu := (s11yy1 + 116130*s11cb1) >> 8
- if s11ru < 0 {
- s11ru = 0
- } else if s11ru > 0xffff {
- s11ru = 0xffff
- }
- if s11gu < 0 {
- s11gu = 0
- } else if s11gu > 0xffff {
- s11gu = 0xffff
- }
- if s11bu < 0 {
- s11bu = 0
- } else if s11bu > 0xffff {
- s11bu = 0xffff
- }
-
+ s01a := float64(s01au)
+ s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
s11r := float64(s11ru)
s11g := float64(s11gu)
s11b := float64(s11bu)
+ s11a := float64(s11au)
s11r = xFrac1*s01r + xFrac0*s11r
s11g = xFrac1*s01g + xFrac0*s11g
s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
s11r = yFrac1*s10r + yFrac0*s11r
s11g = yFrac1*s10g + yFrac0*s11g
s11b = yFrac1*s10b + yFrac0*s11b
- dst.Pix[d+0] = uint8(uint32(s11r) >> 8)
- dst.Pix[d+1] = uint8(uint32(s11g) >> 8)
- dst.Pix[d+2] = uint8(uint32(s11b) >> 8)
- dst.Pix[d+3] = 0xff
+ s11a = yFrac1*s10a + yFrac0*s11a
+ dstColorRGBA64.R = uint16(s11r)
+ dstColorRGBA64.G = uint16(s11g)
+ dstColorRGBA64.B = uint16(s11b)
+ dstColorRGBA64.A = uint16(s11a)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
}
}
}
-func (ablInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
+func (ablInterpolator) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point) {
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
dxf := float64(dr.Min.X+int(dx)) + 0.5
sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
@@ -5147,1887 +3967,608 @@ func (ablInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr imag
yFrac0, yFrac1 = 1, 0
}
- s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s00j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i])<<16 + 1<<15
- s00cb1 := int(src.Cb[s00j]) - 128
- s00cr1 := int(src.Cr[s00j]) - 128
- s00ru := (s00yy1 + 91881*s00cr1) >> 8
- s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
- s00bu := (s00yy1 + 116130*s00cb1) >> 8
- if s00ru < 0 {
- s00ru = 0
- } else if s00ru > 0xffff {
- s00ru = 0xffff
- }
- if s00gu < 0 {
- s00gu = 0
- } else if s00gu > 0xffff {
- s00gu = 0xffff
- }
- if s00bu < 0 {
- s00bu = 0
- } else if s00bu > 0xffff {
- s00bu = 0xffff
- }
-
+ s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
s00r := float64(s00ru)
s00g := float64(s00gu)
s00b := float64(s00bu)
- s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s10j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i])<<16 + 1<<15
- s10cb1 := int(src.Cb[s10j]) - 128
- s10cr1 := int(src.Cr[s10j]) - 128
- s10ru := (s10yy1 + 91881*s10cr1) >> 8
- s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
- s10bu := (s10yy1 + 116130*s10cb1) >> 8
- if s10ru < 0 {
- s10ru = 0
- } else if s10ru > 0xffff {
- s10ru = 0xffff
- }
- if s10gu < 0 {
- s10gu = 0
- } else if s10gu > 0xffff {
- s10gu = 0xffff
- }
- if s10bu < 0 {
- s10bu = 0
- } else if s10bu > 0xffff {
- s10bu = 0xffff
- }
-
+ s00a := float64(s00au)
+ s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
s10r := float64(s10ru)
s10g := float64(s10gu)
s10b := float64(s10bu)
+ s10a := float64(s10au)
s10r = xFrac1*s00r + xFrac0*s10r
s10g = xFrac1*s00g + xFrac0*s10g
s10b = xFrac1*s00b + xFrac0*s10b
- s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s01j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i])<<16 + 1<<15
- s01cb1 := int(src.Cb[s01j]) - 128
- s01cr1 := int(src.Cr[s01j]) - 128
- s01ru := (s01yy1 + 91881*s01cr1) >> 8
- s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
- s01bu := (s01yy1 + 116130*s01cb1) >> 8
- if s01ru < 0 {
- s01ru = 0
- } else if s01ru > 0xffff {
- s01ru = 0xffff
- }
- if s01gu < 0 {
- s01gu = 0
- } else if s01gu > 0xffff {
- s01gu = 0xffff
- }
- if s01bu < 0 {
- s01bu = 0
- } else if s01bu > 0xffff {
- s01bu = 0xffff
- }
-
+ s10a = xFrac1*s00a + xFrac0*s10a
+ s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
s01r := float64(s01ru)
s01g := float64(s01gu)
s01b := float64(s01bu)
- s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s11j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i])<<16 + 1<<15
- s11cb1 := int(src.Cb[s11j]) - 128
- s11cr1 := int(src.Cr[s11j]) - 128
- s11ru := (s11yy1 + 91881*s11cr1) >> 8
- s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
- s11bu := (s11yy1 + 116130*s11cb1) >> 8
- if s11ru < 0 {
- s11ru = 0
- } else if s11ru > 0xffff {
- s11ru = 0xffff
- }
- if s11gu < 0 {
- s11gu = 0
- } else if s11gu > 0xffff {
- s11gu = 0xffff
- }
- if s11bu < 0 {
- s11bu = 0
- } else if s11bu > 0xffff {
- s11bu = 0xffff
- }
-
+ s01a := float64(s01au)
+ s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
s11r := float64(s11ru)
s11g := float64(s11gu)
s11b := float64(s11bu)
+ s11a := float64(s11au)
s11r = xFrac1*s01r + xFrac0*s11r
s11g = xFrac1*s01g + xFrac0*s11g
s11b = xFrac1*s01b + xFrac0*s11b
+ s11a = xFrac1*s01a + xFrac0*s11a
s11r = yFrac1*s10r + yFrac0*s11r
s11g = yFrac1*s10g + yFrac0*s11g
s11b = yFrac1*s10b + yFrac0*s11b
- dst.Pix[d+0] = uint8(uint32(s11r) >> 8)
- dst.Pix[d+1] = uint8(uint32(s11g) >> 8)
- dst.Pix[d+2] = uint8(uint32(s11b) >> 8)
- dst.Pix[d+3] = 0xff
+ s11a = yFrac1*s10a + yFrac0*s11a
+ dstColorRGBA64.R = uint16(s11r)
+ dstColorRGBA64.G = uint16(s11g)
+ dstColorRGBA64.B = uint16(s11b)
+ dstColorRGBA64.A = uint16(s11a)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
}
}
}
-func (ablInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
+func (z *kernelScaler) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
+ if z.dw != int32(dr.Dx()) || z.dh != int32(dr.Dy()) || z.sw != int32(sr.Dx()) || z.sh != int32(sr.Dy()) {
+ z.kernel.Scale(dst, dr, src, sr, opts)
+ return
+ }
+ // adr is the affected destination pixels, relative to dr.Min.
+ adr := dst.Bounds().Intersect(dr).Sub(dr.Min)
+ if adr.Empty() || sr.Empty() {
+ return
+ }
+ op := opts.op()
+ if op == Over && opaque(src) { // TODO: also check that opts.SrcMask == nil.
+ op = Src
+ }
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
+ if _, ok := src.(*image.Uniform); ok && sr.In(src.Bounds()) {
+ Draw(dst, dr, src, src.Bounds().Min, op)
+ return
+ }
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
+ // Create a temporary buffer:
+ // scaleX distributes the source image's columns over the temporary image.
+ // scaleY distributes the temporary image's rows over the destination image.
+ var tmp [][4]float64
+ if z.pool.New != nil {
+ tmpp := z.pool.Get().(*[][4]float64)
+ defer z.pool.Put(tmpp)
+ tmp = *tmpp
+ } else {
+ tmp = z.makeTmpBuf()
+ }
- s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i])<<16 + 1<<15
- s00cb1 := int(src.Cb[s00j]) - 128
- s00cr1 := int(src.Cr[s00j]) - 128
- s00ru := (s00yy1 + 91881*s00cr1) >> 8
- s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
- s00bu := (s00yy1 + 116130*s00cb1) >> 8
- if s00ru < 0 {
- s00ru = 0
- } else if s00ru > 0xffff {
- s00ru = 0xffff
- }
- if s00gu < 0 {
- s00gu = 0
- } else if s00gu > 0xffff {
- s00gu = 0xffff
- }
- if s00bu < 0 {
- s00bu = 0
- } else if s00bu > 0xffff {
- s00bu = 0xffff
- }
-
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i])<<16 + 1<<15
- s10cb1 := int(src.Cb[s10j]) - 128
- s10cr1 := int(src.Cr[s10j]) - 128
- s10ru := (s10yy1 + 91881*s10cr1) >> 8
- s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
- s10bu := (s10yy1 + 116130*s10cb1) >> 8
- if s10ru < 0 {
- s10ru = 0
- } else if s10ru > 0xffff {
- s10ru = 0xffff
- }
- if s10gu < 0 {
- s10gu = 0
- } else if s10gu > 0xffff {
- s10gu = 0xffff
- }
- if s10bu < 0 {
- s10bu = 0
- } else if s10bu > 0xffff {
- s10bu = 0xffff
- }
-
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i])<<16 + 1<<15
- s01cb1 := int(src.Cb[s01j]) - 128
- s01cr1 := int(src.Cr[s01j]) - 128
- s01ru := (s01yy1 + 91881*s01cr1) >> 8
- s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
- s01bu := (s01yy1 + 116130*s01cb1) >> 8
- if s01ru < 0 {
- s01ru = 0
- } else if s01ru > 0xffff {
- s01ru = 0xffff
- }
- if s01gu < 0 {
- s01gu = 0
- } else if s01gu > 0xffff {
- s01gu = 0xffff
- }
- if s01bu < 0 {
- s01bu = 0
- } else if s01bu > 0xffff {
- s01bu = 0xffff
- }
-
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i])<<16 + 1<<15
- s11cb1 := int(src.Cb[s11j]) - 128
- s11cr1 := int(src.Cr[s11j]) - 128
- s11ru := (s11yy1 + 91881*s11cr1) >> 8
- s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
- s11bu := (s11yy1 + 116130*s11cb1) >> 8
- if s11ru < 0 {
- s11ru = 0
- } else if s11ru > 0xffff {
- s11ru = 0xffff
- }
- if s11gu < 0 {
- s11gu = 0
- } else if s11gu > 0xffff {
- s11gu = 0xffff
- }
- if s11bu < 0 {
- s11bu = 0
- } else if s11bu > 0xffff {
- s11bu = 0xffff
- }
-
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- dst.Pix[d+0] = uint8(uint32(s11r) >> 8)
- dst.Pix[d+1] = uint8(uint32(s11g) >> 8)
- dst.Pix[d+2] = uint8(uint32(s11b) >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (ablInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s00yy1 := int(src.Y[s00i])<<16 + 1<<15
- s00cb1 := int(src.Cb[s00j]) - 128
- s00cr1 := int(src.Cr[s00j]) - 128
- s00ru := (s00yy1 + 91881*s00cr1) >> 8
- s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
- s00bu := (s00yy1 + 116130*s00cb1) >> 8
- if s00ru < 0 {
- s00ru = 0
- } else if s00ru > 0xffff {
- s00ru = 0xffff
- }
- if s00gu < 0 {
- s00gu = 0
- } else if s00gu > 0xffff {
- s00gu = 0xffff
- }
- if s00bu < 0 {
- s00bu = 0
- } else if s00bu > 0xffff {
- s00bu = 0xffff
- }
-
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s10yy1 := int(src.Y[s10i])<<16 + 1<<15
- s10cb1 := int(src.Cb[s10j]) - 128
- s10cr1 := int(src.Cr[s10j]) - 128
- s10ru := (s10yy1 + 91881*s10cr1) >> 8
- s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
- s10bu := (s10yy1 + 116130*s10cb1) >> 8
- if s10ru < 0 {
- s10ru = 0
- } else if s10ru > 0xffff {
- s10ru = 0xffff
- }
- if s10gu < 0 {
- s10gu = 0
- } else if s10gu > 0xffff {
- s10gu = 0xffff
- }
- if s10bu < 0 {
- s10bu = 0
- } else if s10bu > 0xffff {
- s10bu = 0xffff
- }
-
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
- s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s01yy1 := int(src.Y[s01i])<<16 + 1<<15
- s01cb1 := int(src.Cb[s01j]) - 128
- s01cr1 := int(src.Cr[s01j]) - 128
- s01ru := (s01yy1 + 91881*s01cr1) >> 8
- s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
- s01bu := (s01yy1 + 116130*s01cb1) >> 8
- if s01ru < 0 {
- s01ru = 0
- } else if s01ru > 0xffff {
- s01ru = 0xffff
- }
- if s01gu < 0 {
- s01gu = 0
- } else if s01gu > 0xffff {
- s01gu = 0xffff
- }
- if s01bu < 0 {
- s01bu = 0
- } else if s01bu > 0xffff {
- s01bu = 0xffff
- }
-
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
- s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- s11yy1 := int(src.Y[s11i])<<16 + 1<<15
- s11cb1 := int(src.Cb[s11j]) - 128
- s11cr1 := int(src.Cr[s11j]) - 128
- s11ru := (s11yy1 + 91881*s11cr1) >> 8
- s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
- s11bu := (s11yy1 + 116130*s11cb1) >> 8
- if s11ru < 0 {
- s11ru = 0
- } else if s11ru > 0xffff {
- s11ru = 0xffff
- }
- if s11gu < 0 {
- s11gu = 0
- } else if s11gu > 0xffff {
- s11gu = 0xffff
- }
- if s11bu < 0 {
- s11bu = 0
- } else if s11bu > 0xffff {
- s11bu = 0xffff
- }
-
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- dst.Pix[d+0] = uint8(uint32(s11r) >> 8)
- dst.Pix[d+1] = uint8(uint32(s11g) >> 8)
- dst.Pix[d+2] = uint8(uint32(s11b) >> 8)
- dst.Pix[d+3] = 0xff
- }
- }
-}
-
-func (ablInterpolator) transform_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- dst.Pix[d+0] = uint8(uint32(s11r) >> 8)
- dst.Pix[d+1] = uint8(uint32(s11g) >> 8)
- dst.Pix[d+2] = uint8(uint32(s11b) >> 8)
- dst.Pix[d+3] = uint8(uint32(s11a) >> 8)
- }
- }
-}
-
-func (ablInterpolator) transform_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point) {
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- dst.Pix[d+0] = uint8(uint32(s11r) >> 8)
- dst.Pix[d+1] = uint8(uint32(s11g) >> 8)
- dst.Pix[d+2] = uint8(uint32(s11b) >> 8)
- dst.Pix[d+3] = uint8(uint32(s11a) >> 8)
- }
- }
-}
-
-func (ablInterpolator) transform_Image_Image_Over(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point) {
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- dstColorRGBA64.R = uint16(s11r)
- dstColorRGBA64.G = uint16(s11g)
- dstColorRGBA64.B = uint16(s11b)
- dstColorRGBA64.A = uint16(s11a)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- }
- }
-}
-
-func (ablInterpolator) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point) {
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- sx -= 0.5
- sx0 := int(sx)
- xFrac0 := sx - float64(sx0)
- xFrac1 := 1 - xFrac0
- sx0 += bias.X
- sx1 := sx0 + 1
- if sx0 < sr.Min.X {
- sx0, sx1 = sr.Min.X, sr.Min.X
- xFrac0, xFrac1 = 0, 1
- } else if sx1 >= sr.Max.X {
- sx0, sx1 = sr.Max.X-1, sr.Max.X-1
- xFrac0, xFrac1 = 1, 0
- }
-
- sy -= 0.5
- sy0 := int(sy)
- yFrac0 := sy - float64(sy0)
- yFrac1 := 1 - yFrac0
- sy0 += bias.Y
- sy1 := sy0 + 1
- if sy0 < sr.Min.Y {
- sy0, sy1 = sr.Min.Y, sr.Min.Y
- yFrac0, yFrac1 = 0, 1
- } else if sy1 >= sr.Max.Y {
- sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
- yFrac0, yFrac1 = 1, 0
- }
-
- s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
- s00r := float64(s00ru)
- s00g := float64(s00gu)
- s00b := float64(s00bu)
- s00a := float64(s00au)
- s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
- s10r := float64(s10ru)
- s10g := float64(s10gu)
- s10b := float64(s10bu)
- s10a := float64(s10au)
- s10r = xFrac1*s00r + xFrac0*s10r
- s10g = xFrac1*s00g + xFrac0*s10g
- s10b = xFrac1*s00b + xFrac0*s10b
- s10a = xFrac1*s00a + xFrac0*s10a
- s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
- s01r := float64(s01ru)
- s01g := float64(s01gu)
- s01b := float64(s01bu)
- s01a := float64(s01au)
- s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
- s11r := float64(s11ru)
- s11g := float64(s11gu)
- s11b := float64(s11bu)
- s11a := float64(s11au)
- s11r = xFrac1*s01r + xFrac0*s11r
- s11g = xFrac1*s01g + xFrac0*s11g
- s11b = xFrac1*s01b + xFrac0*s11b
- s11a = xFrac1*s01a + xFrac0*s11a
- s11r = yFrac1*s10r + yFrac0*s11r
- s11g = yFrac1*s10g + yFrac0*s11g
- s11b = yFrac1*s10b + yFrac0*s11b
- s11a = yFrac1*s10a + yFrac0*s11a
- dstColorRGBA64.R = uint16(s11r)
- dstColorRGBA64.G = uint16(s11g)
- dstColorRGBA64.B = uint16(s11b)
- dstColorRGBA64.A = uint16(s11a)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
- }
- }
-}
-
-func (z *kernelScaler) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
- if z.dw != int32(dr.Dx()) || z.dh != int32(dr.Dy()) || z.sw != int32(sr.Dx()) || z.sh != int32(sr.Dy()) {
- z.kernel.Scale(dst, dr, src, sr, opts)
- return
- }
- // adr is the affected destination pixels, relative to dr.Min.
- adr := dst.Bounds().Intersect(dr).Sub(dr.Min)
- if adr.Empty() || sr.Empty() {
- return
- }
-
- if _, ok := src.(*image.Uniform); ok && sr.In(src.Bounds()) {
- Draw(dst, dr, src, src.Bounds().Min, opts.op())
- return
- }
-
- // Create a temporary buffer:
- // scaleX distributes the source image's columns over the temporary image.
- // scaleY distributes the temporary image's rows over the destination image.
- var tmp [][4]float64
- if z.pool.New != nil {
- tmpp := z.pool.Get().(*[][4]float64)
- defer z.pool.Put(tmpp)
- tmp = *tmpp
- } else {
- tmp = z.makeTmpBuf()
- }
-
- // sr is the source pixels. If it extends beyond the src bounds,
- // we cannot use the type-specific fast paths, as they access
- // the Pix fields directly without bounds checking.
- if !sr.In(src.Bounds()) {
- z.scaleX_Image(tmp, src, sr)
- } else {
- switch src := src.(type) {
- case *image.Gray:
- z.scaleX_Gray(tmp, src, sr)
- case *image.NRGBA:
- z.scaleX_NRGBA(tmp, src, sr)
- case *image.RGBA:
- z.scaleX_RGBA(tmp, src, sr)
- case *image.YCbCr:
- switch src.SubsampleRatio {
- default:
- z.scaleX_Image(tmp, src, sr)
- case image.YCbCrSubsampleRatio444:
- z.scaleX_YCbCr444(tmp, src, sr)
- case image.YCbCrSubsampleRatio422:
- z.scaleX_YCbCr422(tmp, src, sr)
- case image.YCbCrSubsampleRatio420:
- z.scaleX_YCbCr420(tmp, src, sr)
- case image.YCbCrSubsampleRatio440:
- z.scaleX_YCbCr440(tmp, src, sr)
- }
- default:
- z.scaleX_Image(tmp, src, sr)
- }
- }
-
- switch opts.op() {
- case Over:
- switch dst := dst.(type) {
- case *image.RGBA:
- z.scaleY_RGBA_Over(dst, dr, adr, tmp)
- default:
- z.scaleY_Image_Over(dst, dr, adr, tmp)
- }
- case Src:
- switch dst := dst.(type) {
- case *image.RGBA:
- z.scaleY_RGBA_Src(dst, dr, adr, tmp)
- default:
- z.scaleY_Image_Src(dst, dr, adr, tmp)
- }
- }
-}
-
-func (q *Kernel) Transform(dst Image, s2d *f64.Aff3, src image.Image, sr image.Rectangle, opts *Options) {
- dr := transformRect(s2d, &sr)
- // adr is the affected destination pixels.
- adr := dst.Bounds().Intersect(dr)
- if adr.Empty() || sr.Empty() {
- return
- }
- d2s := invert(s2d)
- // bias is a translation of the mapping from dst co-ordinates to
- // src co-ordinates such that the latter temporarily have
- // non-negative X and Y co-ordinates. This allows us to write
- // int(f) instead of int(math.Floor(f)), since "round to zero" and
- // "round down" are equivalent when f >= 0, but the former is much
- // cheaper. The X-- and Y-- are because the TransformLeaf methods
- // have a "sx -= 0.5" adjustment.
- bias := transformRect(&d2s, &adr).Min
- bias.X--
- bias.Y--
- d2s[2] -= float64(bias.X)
- d2s[5] -= float64(bias.Y)
- // Make adr relative to dr.Min.
- adr = adr.Sub(dr.Min)
-
- if u, ok := src.(*image.Uniform); ok && sr.In(src.Bounds()) {
- transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, opts.op())
- return
- }
-
- xscale := abs(d2s[0])
- if s := abs(d2s[1]); xscale < s {
- xscale = s
- }
- yscale := abs(d2s[3])
- if s := abs(d2s[4]); yscale < s {
- yscale = s
- }
-
- // sr is the source pixels. If it extends beyond the src bounds,
- // we cannot use the type-specific fast paths, as they access
- // the Pix fields directly without bounds checking.
- if !sr.In(src.Bounds()) {
- switch opts.op() {
- case Over:
- q.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- case Src:
- q.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- }
- } else {
- switch opts.op() {
- case Over:
- switch dst := dst.(type) {
- case *image.RGBA:
- switch src := src.(type) {
- case *image.Gray:
- q.transform_RGBA_Gray_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- case *image.NRGBA:
- q.transform_RGBA_NRGBA_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- case *image.RGBA:
- q.transform_RGBA_RGBA_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- case *image.YCbCr:
- switch src.SubsampleRatio {
- default:
- q.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- case image.YCbCrSubsampleRatio444:
- q.transform_RGBA_YCbCr444_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- case image.YCbCrSubsampleRatio422:
- q.transform_RGBA_YCbCr422_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- case image.YCbCrSubsampleRatio420:
- q.transform_RGBA_YCbCr420_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- case image.YCbCrSubsampleRatio440:
- q.transform_RGBA_YCbCr440_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- }
- default:
- q.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- }
- default:
- switch src := src.(type) {
- default:
- q.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- }
- }
- case Src:
- switch dst := dst.(type) {
- case *image.RGBA:
- switch src := src.(type) {
- case *image.Gray:
- q.transform_RGBA_Gray_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- case *image.NRGBA:
- q.transform_RGBA_NRGBA_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- case *image.RGBA:
- q.transform_RGBA_RGBA_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- case *image.YCbCr:
- switch src.SubsampleRatio {
- default:
- q.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- case image.YCbCrSubsampleRatio444:
- q.transform_RGBA_YCbCr444_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- case image.YCbCrSubsampleRatio422:
- q.transform_RGBA_YCbCr422_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- case image.YCbCrSubsampleRatio420:
- q.transform_RGBA_YCbCr420_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- case image.YCbCrSubsampleRatio440:
- q.transform_RGBA_YCbCr440_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- }
- default:
- q.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- }
- default:
- switch src := src.(type) {
- default:
- q.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
- }
- }
- }
- }
-}
-
-func (z *kernelScaler) scaleX_Gray(tmp [][4]float64, src *image.Gray, sr image.Rectangle) {
- t := 0
- for y := int32(0); y < z.sh; y++ {
- for _, s := range z.horizontal.sources {
- var pr float64
- for _, c := range z.horizontal.contribs[s.i:s.j] {
- pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
- pru := uint32(src.Pix[pi]) * 0x101
- pr += float64(pru) * c.weight
- }
- pr *= s.invTotalWeightFFFF
- tmp[t] = [4]float64{
- pr,
- pr,
- pr,
- 1,
- }
- t++
- }
- }
-}
-
-func (z *kernelScaler) scaleX_NRGBA(tmp [][4]float64, src *image.NRGBA, sr image.Rectangle) {
- t := 0
- for y := int32(0); y < z.sh; y++ {
- for _, s := range z.horizontal.sources {
- var pr, pg, pb, pa float64
- for _, c := range z.horizontal.contribs[s.i:s.j] {
- pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(c.coord)-src.Rect.Min.X)*4
- pau := uint32(src.Pix[pi+3]) * 0x101
- pru := uint32(src.Pix[pi+0]) * pau / 0xff
- pgu := uint32(src.Pix[pi+1]) * pau / 0xff
- pbu := uint32(src.Pix[pi+2]) * pau / 0xff
- pr += float64(pru) * c.weight
- pg += float64(pgu) * c.weight
- pb += float64(pbu) * c.weight
- pa += float64(pau) * c.weight
- }
- tmp[t] = [4]float64{
- pr * s.invTotalWeightFFFF,
- pg * s.invTotalWeightFFFF,
- pb * s.invTotalWeightFFFF,
- pa * s.invTotalWeightFFFF,
- }
- t++
- }
- }
-}
-
-func (z *kernelScaler) scaleX_RGBA(tmp [][4]float64, src *image.RGBA, sr image.Rectangle) {
- t := 0
- for y := int32(0); y < z.sh; y++ {
- for _, s := range z.horizontal.sources {
- var pr, pg, pb, pa float64
- for _, c := range z.horizontal.contribs[s.i:s.j] {
- pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(c.coord)-src.Rect.Min.X)*4
- pru := uint32(src.Pix[pi+0]) * 0x101
- pgu := uint32(src.Pix[pi+1]) * 0x101
- pbu := uint32(src.Pix[pi+2]) * 0x101
- pau := uint32(src.Pix[pi+3]) * 0x101
- pr += float64(pru) * c.weight
- pg += float64(pgu) * c.weight
- pb += float64(pbu) * c.weight
- pa += float64(pau) * c.weight
- }
- tmp[t] = [4]float64{
- pr * s.invTotalWeightFFFF,
- pg * s.invTotalWeightFFFF,
- pb * s.invTotalWeightFFFF,
- pa * s.invTotalWeightFFFF,
- }
- t++
- }
- }
-}
-
-func (z *kernelScaler) scaleX_YCbCr444(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle) {
- t := 0
- for y := int32(0); y < z.sh; y++ {
- for _, s := range z.horizontal.sources {
- var pr, pg, pb float64
- for _, c := range z.horizontal.contribs[s.i:s.j] {
- pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
- pj := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi])<<16 + 1<<15
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pru := (pyy1 + 91881*pcr1) >> 8
- pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pbu := (pyy1 + 116130*pcb1) >> 8
- if pru < 0 {
- pru = 0
- } else if pru > 0xffff {
- pru = 0xffff
- }
- if pgu < 0 {
- pgu = 0
- } else if pgu > 0xffff {
- pgu = 0xffff
- }
- if pbu < 0 {
- pbu = 0
- } else if pbu > 0xffff {
- pbu = 0xffff
- }
-
- pr += float64(pru) * c.weight
- pg += float64(pgu) * c.weight
- pb += float64(pbu) * c.weight
- }
- tmp[t] = [4]float64{
- pr * s.invTotalWeightFFFF,
- pg * s.invTotalWeightFFFF,
- pb * s.invTotalWeightFFFF,
- 1,
- }
- t++
- }
- }
-}
-
-func (z *kernelScaler) scaleX_YCbCr422(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle) {
- t := 0
- for y := int32(0); y < z.sh; y++ {
- for _, s := range z.horizontal.sources {
- var pr, pg, pb float64
- for _, c := range z.horizontal.contribs[s.i:s.j] {
- pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
- pj := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(c.coord))/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi])<<16 + 1<<15
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pru := (pyy1 + 91881*pcr1) >> 8
- pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pbu := (pyy1 + 116130*pcb1) >> 8
- if pru < 0 {
- pru = 0
- } else if pru > 0xffff {
- pru = 0xffff
- }
- if pgu < 0 {
- pgu = 0
- } else if pgu > 0xffff {
- pgu = 0xffff
- }
- if pbu < 0 {
- pbu = 0
- } else if pbu > 0xffff {
- pbu = 0xffff
- }
-
- pr += float64(pru) * c.weight
- pg += float64(pgu) * c.weight
- pb += float64(pbu) * c.weight
- }
- tmp[t] = [4]float64{
- pr * s.invTotalWeightFFFF,
- pg * s.invTotalWeightFFFF,
- pb * s.invTotalWeightFFFF,
- 1,
- }
- t++
- }
- }
-}
-
-func (z *kernelScaler) scaleX_YCbCr420(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle) {
- t := 0
- for y := int32(0); y < z.sh; y++ {
- for _, s := range z.horizontal.sources {
- var pr, pg, pb float64
- for _, c := range z.horizontal.contribs[s.i:s.j] {
- pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
- 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)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi])<<16 + 1<<15
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pru := (pyy1 + 91881*pcr1) >> 8
- pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pbu := (pyy1 + 116130*pcb1) >> 8
- if pru < 0 {
- pru = 0
- } else if pru > 0xffff {
- pru = 0xffff
- }
- if pgu < 0 {
- pgu = 0
- } else if pgu > 0xffff {
- pgu = 0xffff
- }
- if pbu < 0 {
- pbu = 0
- } else if pbu > 0xffff {
- pbu = 0xffff
- }
-
- pr += float64(pru) * c.weight
- pg += float64(pgu) * c.weight
- pb += float64(pbu) * c.weight
- }
- tmp[t] = [4]float64{
- pr * s.invTotalWeightFFFF,
- pg * s.invTotalWeightFFFF,
- pb * s.invTotalWeightFFFF,
- 1,
- }
- t++
- }
- }
-}
-
-func (z *kernelScaler) scaleX_YCbCr440(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle) {
- t := 0
- for y := int32(0); y < z.sh; y++ {
- for _, s := range z.horizontal.sources {
- var pr, pg, pb float64
- for _, c := range z.horizontal.contribs[s.i:s.j] {
- pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
- pj := ((sr.Min.Y+int(y))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi])<<16 + 1<<15
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pru := (pyy1 + 91881*pcr1) >> 8
- pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pbu := (pyy1 + 116130*pcb1) >> 8
- if pru < 0 {
- pru = 0
- } else if pru > 0xffff {
- pru = 0xffff
- }
- if pgu < 0 {
- pgu = 0
- } else if pgu > 0xffff {
- pgu = 0xffff
- }
- if pbu < 0 {
- pbu = 0
- } else if pbu > 0xffff {
- pbu = 0xffff
- }
-
- pr += float64(pru) * c.weight
- pg += float64(pgu) * c.weight
- pb += float64(pbu) * c.weight
- }
- tmp[t] = [4]float64{
- pr * s.invTotalWeightFFFF,
- pg * s.invTotalWeightFFFF,
- pb * s.invTotalWeightFFFF,
- 1,
- }
- t++
- }
- }
-}
-
-func (z *kernelScaler) scaleX_Image(tmp [][4]float64, src image.Image, sr image.Rectangle) {
- t := 0
- for y := int32(0); y < z.sh; y++ {
- for _, s := range z.horizontal.sources {
- var pr, pg, pb, pa float64
- for _, c := range z.horizontal.contribs[s.i:s.j] {
- pru, pgu, pbu, pau := src.At(sr.Min.X+int(c.coord), sr.Min.Y+int(y)).RGBA()
- pr += float64(pru) * c.weight
- pg += float64(pgu) * c.weight
- pb += float64(pbu) * c.weight
- pa += float64(pau) * c.weight
- }
- tmp[t] = [4]float64{
- pr * s.invTotalWeightFFFF,
- pg * s.invTotalWeightFFFF,
- pb * s.invTotalWeightFFFF,
- pa * s.invTotalWeightFFFF,
- }
- t++
- }
- }
-}
-
-func (z *kernelScaler) scaleY_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, tmp [][4]float64) {
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- d := (dr.Min.Y+adr.Min.Y-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+int(dx)-dst.Rect.Min.X)*4
- for _, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
- var pr, pg, pb, pa float64
- for _, c := range z.vertical.contribs[s.i:s.j] {
- p := &tmp[c.coord*z.dw+dx]
- pr += p[0] * c.weight
- pg += p[1] * c.weight
- pb += p[2] * c.weight
- pa += p[3] * c.weight
- }
- dst.Pix[d+0] = uint8(ftou(pr*s.invTotalWeight) >> 8)
- dst.Pix[d+1] = uint8(ftou(pg*s.invTotalWeight) >> 8)
- dst.Pix[d+2] = uint8(ftou(pb*s.invTotalWeight) >> 8)
- dst.Pix[d+3] = uint8(ftou(pa*s.invTotalWeight) >> 8)
- d += dst.Stride
- }
- }
-}
-
-func (z *kernelScaler) scaleY_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, tmp [][4]float64) {
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- d := (dr.Min.Y+adr.Min.Y-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+int(dx)-dst.Rect.Min.X)*4
- for _, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
- var pr, pg, pb, pa float64
- for _, c := range z.vertical.contribs[s.i:s.j] {
- p := &tmp[c.coord*z.dw+dx]
- pr += p[0] * c.weight
- pg += p[1] * c.weight
- pb += p[2] * c.weight
- pa += p[3] * c.weight
+ // sr is the source pixels. If it extends beyond the src bounds,
+ // we cannot use the type-specific fast paths, as they access
+ // the Pix fields directly without bounds checking.
+ if !sr.In(src.Bounds()) {
+ z.scaleX_Image(tmp, src, sr)
+ } else {
+ switch src := src.(type) {
+ case *image.Gray:
+ z.scaleX_Gray(tmp, src, sr)
+ case *image.NRGBA:
+ z.scaleX_NRGBA(tmp, src, sr)
+ case *image.RGBA:
+ z.scaleX_RGBA(tmp, src, sr)
+ case *image.YCbCr:
+ switch src.SubsampleRatio {
+ default:
+ z.scaleX_Image(tmp, src, sr)
+ case image.YCbCrSubsampleRatio444:
+ z.scaleX_YCbCr444(tmp, src, sr)
+ case image.YCbCrSubsampleRatio422:
+ z.scaleX_YCbCr422(tmp, src, sr)
+ case image.YCbCrSubsampleRatio420:
+ z.scaleX_YCbCr420(tmp, src, sr)
+ case image.YCbCrSubsampleRatio440:
+ z.scaleX_YCbCr440(tmp, src, sr)
}
- dst.Pix[d+0] = uint8(ftou(pr*s.invTotalWeight) >> 8)
- dst.Pix[d+1] = uint8(ftou(pg*s.invTotalWeight) >> 8)
- dst.Pix[d+2] = uint8(ftou(pb*s.invTotalWeight) >> 8)
- dst.Pix[d+3] = uint8(ftou(pa*s.invTotalWeight) >> 8)
- d += dst.Stride
+ default:
+ z.scaleX_Image(tmp, src, sr)
}
}
-}
-func (z *kernelScaler) scaleY_Image_Over(dst Image, dr, adr image.Rectangle, tmp [][4]float64) {
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- for dy, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
- var pr, pg, pb, pa float64
- for _, c := range z.vertical.contribs[s.i:s.j] {
- p := &tmp[c.coord*z.dw+dx]
- pr += p[0] * c.weight
- pg += p[1] * c.weight
- pb += p[2] * c.weight
- pa += p[3] * c.weight
- }
- dstColorRGBA64.R = ftou(pr * s.invTotalWeight)
- dstColorRGBA64.G = ftou(pg * s.invTotalWeight)
- dstColorRGBA64.B = ftou(pb * s.invTotalWeight)
- dstColorRGBA64.A = ftou(pa * s.invTotalWeight)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColor)
+ switch op {
+ case Over:
+ switch dst := dst.(type) {
+ case *image.RGBA:
+ z.scaleY_RGBA_Over(dst, dr, adr, tmp)
+ default:
+ z.scaleY_Image_Over(dst, dr, adr, tmp)
}
- }
-}
-
-func (z *kernelScaler) scaleY_Image_Src(dst Image, dr, adr image.Rectangle, tmp [][4]float64) {
- dstColorRGBA64 := &color.RGBA64{}
- dstColor := color.Color(dstColorRGBA64)
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
- for dy, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
- var pr, pg, pb, pa float64
- for _, c := range z.vertical.contribs[s.i:s.j] {
- p := &tmp[c.coord*z.dw+dx]
- pr += p[0] * c.weight
- pg += p[1] * c.weight
- pb += p[2] * c.weight
- pa += p[3] * c.weight
- }
- dstColorRGBA64.R = ftou(pr * s.invTotalWeight)
- dstColorRGBA64.G = ftou(pg * s.invTotalWeight)
- dstColorRGBA64.B = ftou(pb * s.invTotalWeight)
- dstColorRGBA64.A = ftou(pa * s.invTotalWeight)
- dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColor)
+ case Src:
+ switch dst := dst.(type) {
+ case *image.RGBA:
+ z.scaleY_RGBA_Src(dst, dr, adr, tmp)
+ default:
+ z.scaleY_Image_Src(dst, dr, adr, tmp)
}
}
}
-func (q *Kernel) transform_RGBA_Gray_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point, xscale, yscale float64) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
+func (q *Kernel) Transform(dst Image, s2d *f64.Aff3, src image.Image, sr image.Rectangle, opts *Options) {
+ dr := transformRect(s2d, &sr)
+ // adr is the affected destination pixels.
+ adr := dst.Bounds().Intersect(dr)
+ if adr.Empty() || sr.Empty() {
+ return
}
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
+ op := opts.op()
+ if op == Over && opaque(src) { // TODO: also check that opts.SrcMask == nil.
+ op = Src
}
+ d2s := invert(s2d)
+ // bias is a translation of the mapping from dst co-ordinates to
+ // src co-ordinates such that the latter temporarily have
+ // non-negative X and Y co-ordinates. This allows us to write
+ // int(f) instead of int(math.Floor(f)), since "round to zero" and
+ // "round down" are equivalent when f >= 0, but the former is much
+ // cheaper. The X-- and Y-- are because the TransformLeaf methods
+ // have a "sx -= 0.5" adjustment.
+ bias := transformRect(&d2s, &adr).Min
+ bias.X--
+ bias.Y--
+ d2s[2] -= float64(bias.X)
+ d2s[5] -= float64(bias.Y)
+ // Make adr relative to dr.Min.
+ adr = adr.Sub(dr.Min)
- xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
- }
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
- }
-
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
- }
- xWeights[kx-ix] = xWeight
- totalXWeight += xWeight
- }
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
- }
-
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
- }
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
- }
-
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
- }
- yWeights[ky-iy] = yWeight
- totalYWeight += yWeight
- }
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
- }
-
- var pr float64
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky-iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.Stride + (kx - src.Rect.Min.X)
- pru := uint32(src.Pix[pi]) * 0x101
- pr += float64(pru) * w
- }
- }
- }
- }
- out := uint8(fffftou(pr) >> 8)
- dst.Pix[d+0] = out
- dst.Pix[d+1] = out
- dst.Pix[d+2] = out
- dst.Pix[d+3] = 0xff
- }
+ if u, ok := src.(*image.Uniform); ok && sr.In(src.Bounds()) {
+ transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
+ return
}
-}
-func (q *Kernel) transform_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point, xscale, yscale float64) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
+ xscale := abs(d2s[0])
+ if s := abs(d2s[1]); xscale < s {
+ xscale = s
}
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
+ yscale := abs(d2s[3])
+ if s := abs(d2s[4]); yscale < s {
+ yscale = s
}
- xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
- }
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
- }
-
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
+ // sr is the source pixels. If it extends beyond the src bounds,
+ // we cannot use the type-specific fast paths, as they access
+ // the Pix fields directly without bounds checking.
+ if !sr.In(src.Bounds()) {
+ switch op {
+ case Over:
+ q.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
+ case Src:
+ q.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
+ }
+ } else {
+ switch op {
+ case Over:
+ switch dst := dst.(type) {
+ case *image.RGBA:
+ switch src := src.(type) {
+ case *image.NRGBA:
+ q.transform_RGBA_NRGBA_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
+ case *image.RGBA:
+ q.transform_RGBA_RGBA_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
+ default:
+ q.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
}
- xWeights[kx-ix] = xWeight
- totalXWeight += xWeight
- }
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
- }
-
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
- }
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
- }
-
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
+ default:
+ switch src := src.(type) {
+ default:
+ q.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
}
- yWeights[ky-iy] = yWeight
- totalYWeight += yWeight
- }
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
}
-
- var pr float64
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky-iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.Stride + (kx - src.Rect.Min.X)
- pru := uint32(src.Pix[pi]) * 0x101
- pr += float64(pru) * w
- }
+ case Src:
+ switch dst := dst.(type) {
+ case *image.RGBA:
+ switch src := src.(type) {
+ case *image.Gray:
+ q.transform_RGBA_Gray_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
+ case *image.NRGBA:
+ q.transform_RGBA_NRGBA_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
+ case *image.RGBA:
+ q.transform_RGBA_RGBA_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
+ case *image.YCbCr:
+ switch src.SubsampleRatio {
+ default:
+ q.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
+ case image.YCbCrSubsampleRatio444:
+ q.transform_RGBA_YCbCr444_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
+ case image.YCbCrSubsampleRatio422:
+ q.transform_RGBA_YCbCr422_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
+ case image.YCbCrSubsampleRatio420:
+ q.transform_RGBA_YCbCr420_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
+ case image.YCbCrSubsampleRatio440:
+ q.transform_RGBA_YCbCr440_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
}
+ default:
+ q.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
+ }
+ default:
+ switch src := src.(type) {
+ default:
+ q.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale)
}
}
- out := uint8(fffftou(pr) >> 8)
- dst.Pix[d+0] = out
- dst.Pix[d+1] = out
- dst.Pix[d+2] = out
- dst.Pix[d+3] = 0xff
}
}
}
-func (q *Kernel) transform_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
- }
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
- }
-
- xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
- }
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
- }
-
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
- }
- xWeights[kx-ix] = xWeight
- totalXWeight += xWeight
- }
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
- }
-
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
+func (z *kernelScaler) scaleX_Gray(tmp [][4]float64, src *image.Gray, sr image.Rectangle) {
+ t := 0
+ for y := int32(0); y < z.sh; y++ {
+ for _, s := range z.horizontal.sources {
+ var pr float64
+ for _, c := range z.horizontal.contribs[s.i:s.j] {
+ pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
+ pru := uint32(src.Pix[pi]) * 0x101
+ pr += float64(pru) * c.weight
}
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
+ pr *= s.invTotalWeightFFFF
+ tmp[t] = [4]float64{
+ pr,
+ pr,
+ pr,
+ 1,
}
+ t++
+ }
+ }
+}
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
- }
- yWeights[ky-iy] = yWeight
- totalYWeight += yWeight
+func (z *kernelScaler) scaleX_NRGBA(tmp [][4]float64, src *image.NRGBA, sr image.Rectangle) {
+ t := 0
+ for y := int32(0); y < z.sh; y++ {
+ for _, s := range z.horizontal.sources {
+ var pr, pg, pb, pa float64
+ for _, c := range z.horizontal.contribs[s.i:s.j] {
+ pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(c.coord)-src.Rect.Min.X)*4
+ pau := uint32(src.Pix[pi+3]) * 0x101
+ pru := uint32(src.Pix[pi+0]) * pau / 0xff
+ pgu := uint32(src.Pix[pi+1]) * pau / 0xff
+ pbu := uint32(src.Pix[pi+2]) * pau / 0xff
+ pr += float64(pru) * c.weight
+ pg += float64(pgu) * c.weight
+ pb += float64(pbu) * c.weight
+ pa += float64(pau) * c.weight
}
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
+ tmp[t] = [4]float64{
+ pr * s.invTotalWeightFFFF,
+ pg * s.invTotalWeightFFFF,
+ pb * s.invTotalWeightFFFF,
+ pa * s.invTotalWeightFFFF,
}
+ t++
+ }
+ }
+}
+func (z *kernelScaler) scaleX_RGBA(tmp [][4]float64, src *image.RGBA, sr image.Rectangle) {
+ t := 0
+ for y := int32(0); y < z.sh; y++ {
+ for _, s := range z.horizontal.sources {
var pr, pg, pb, pa float64
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky-iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
- pau := uint32(src.Pix[pi+3]) * 0x101
- pru := uint32(src.Pix[pi+0]) * pau / 0xff
- pgu := uint32(src.Pix[pi+1]) * pau / 0xff
- pbu := uint32(src.Pix[pi+2]) * pau / 0xff
- pr += float64(pru) * w
- pg += float64(pgu) * w
- pb += float64(pbu) * w
- pa += float64(pau) * w
- }
- }
- }
+ for _, c := range z.horizontal.contribs[s.i:s.j] {
+ pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(c.coord)-src.Rect.Min.X)*4
+ pru := uint32(src.Pix[pi+0]) * 0x101
+ pgu := uint32(src.Pix[pi+1]) * 0x101
+ pbu := uint32(src.Pix[pi+2]) * 0x101
+ pau := uint32(src.Pix[pi+3]) * 0x101
+ pr += float64(pru) * c.weight
+ pg += float64(pgu) * c.weight
+ pb += float64(pbu) * c.weight
+ pa += float64(pau) * c.weight
}
- dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
- dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
- dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
- dst.Pix[d+3] = uint8(fffftou(pa) >> 8)
+ tmp[t] = [4]float64{
+ pr * s.invTotalWeightFFFF,
+ pg * s.invTotalWeightFFFF,
+ pb * s.invTotalWeightFFFF,
+ pa * s.invTotalWeightFFFF,
+ }
+ t++
}
}
}
-func (q *Kernel) transform_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
- }
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
- }
-
- xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
-
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
-
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
- }
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
- }
+func (z *kernelScaler) scaleX_YCbCr444(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle) {
+ t := 0
+ for y := int32(0); y < z.sh; y++ {
+ for _, s := range z.horizontal.sources {
+ var pr, pg, pb float64
+ for _, c := range z.horizontal.contribs[s.i:s.j] {
+ pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
+ pj := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi])<<16 + 1<<15
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pru := (pyy1 + 91881*pcr1) >> 8
+ pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pbu := (pyy1 + 116130*pcb1) >> 8
+ if pru < 0 {
+ pru = 0
+ } else if pru > 0xffff {
+ pru = 0xffff
+ }
+ if pgu < 0 {
+ pgu = 0
+ } else if pgu > 0xffff {
+ pgu = 0xffff
+ }
+ if pbu < 0 {
+ pbu = 0
+ } else if pbu > 0xffff {
+ pbu = 0xffff
}
- xWeights[kx-ix] = xWeight
- totalXWeight += xWeight
- }
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
- }
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
+ pr += float64(pru) * c.weight
+ pg += float64(pgu) * c.weight
+ pb += float64(pbu) * c.weight
}
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
+ tmp[t] = [4]float64{
+ pr * s.invTotalWeightFFFF,
+ pg * s.invTotalWeightFFFF,
+ pb * s.invTotalWeightFFFF,
+ 1,
}
+ t++
+ }
+ }
+}
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
+func (z *kernelScaler) scaleX_YCbCr422(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle) {
+ t := 0
+ for y := int32(0); y < z.sh; y++ {
+ for _, s := range z.horizontal.sources {
+ var pr, pg, pb float64
+ for _, c := range z.horizontal.contribs[s.i:s.j] {
+ pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
+ pj := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(c.coord))/2 - src.Rect.Min.X/2)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi])<<16 + 1<<15
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pru := (pyy1 + 91881*pcr1) >> 8
+ pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pbu := (pyy1 + 116130*pcb1) >> 8
+ if pru < 0 {
+ pru = 0
+ } else if pru > 0xffff {
+ pru = 0xffff
}
- yWeights[ky-iy] = yWeight
- totalYWeight += yWeight
+ if pgu < 0 {
+ pgu = 0
+ } else if pgu > 0xffff {
+ pgu = 0xffff
+ }
+ if pbu < 0 {
+ pbu = 0
+ } else if pbu > 0xffff {
+ pbu = 0xffff
+ }
+
+ pr += float64(pru) * c.weight
+ pg += float64(pgu) * c.weight
+ pb += float64(pbu) * c.weight
}
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
+ tmp[t] = [4]float64{
+ pr * s.invTotalWeightFFFF,
+ pg * s.invTotalWeightFFFF,
+ pb * s.invTotalWeightFFFF,
+ 1,
}
+ t++
+ }
+ }
+}
- var pr, pg, pb, pa float64
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky-iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
- pau := uint32(src.Pix[pi+3]) * 0x101
- pru := uint32(src.Pix[pi+0]) * pau / 0xff
- pgu := uint32(src.Pix[pi+1]) * pau / 0xff
- pbu := uint32(src.Pix[pi+2]) * pau / 0xff
- pr += float64(pru) * w
- pg += float64(pgu) * w
- pb += float64(pbu) * w
- pa += float64(pau) * w
- }
- }
+func (z *kernelScaler) scaleX_YCbCr420(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle) {
+ t := 0
+ for y := int32(0); y < z.sh; y++ {
+ for _, s := range z.horizontal.sources {
+ var pr, pg, pb float64
+ for _, c := range z.horizontal.contribs[s.i:s.j] {
+ pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
+ 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)
+
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi])<<16 + 1<<15
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pru := (pyy1 + 91881*pcr1) >> 8
+ pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pbu := (pyy1 + 116130*pcb1) >> 8
+ if pru < 0 {
+ pru = 0
+ } else if pru > 0xffff {
+ pru = 0xffff
+ }
+ if pgu < 0 {
+ pgu = 0
+ } else if pgu > 0xffff {
+ pgu = 0xffff
+ }
+ if pbu < 0 {
+ pbu = 0
+ } else if pbu > 0xffff {
+ pbu = 0xffff
}
+
+ pr += float64(pru) * c.weight
+ pg += float64(pgu) * c.weight
+ pb += float64(pbu) * c.weight
}
- dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
- dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
- dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
- dst.Pix[d+3] = uint8(fffftou(pa) >> 8)
+ tmp[t] = [4]float64{
+ pr * s.invTotalWeightFFFF,
+ pg * s.invTotalWeightFFFF,
+ pb * s.invTotalWeightFFFF,
+ 1,
+ }
+ t++
}
}
}
-func (q *Kernel) transform_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64) {
- // When shrinking, broaden the effective kernel support so that we still
- // visit every source pixel.
- xHalfWidth, xKernelArgScale := q.Support, 1.0
- if xscale > 1 {
- xHalfWidth *= xscale
- xKernelArgScale = 1 / xscale
- }
- yHalfWidth, yKernelArgScale := q.Support, 1.0
- if yscale > 1 {
- yHalfWidth *= yscale
- yKernelArgScale = 1 / yscale
- }
-
- xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
- yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
+func (z *kernelScaler) scaleX_YCbCr440(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle) {
+ t := 0
+ for y := int32(0); y < z.sh; y++ {
+ for _, s := range z.horizontal.sources {
+ var pr, pg, pb float64
+ for _, c := range z.horizontal.contribs[s.i:s.j] {
+ pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
+ pj := ((sr.Min.Y+int(y))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
- for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
- dyf := float64(dr.Min.Y+int(dy)) + 0.5
- d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
- for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
- dxf := float64(dr.Min.X+int(dx)) + 0.5
- sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
- sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5]
- if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
- continue
- }
+ // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
+ pyy1 := int(src.Y[pi])<<16 + 1<<15
+ pcb1 := int(src.Cb[pj]) - 128
+ pcr1 := int(src.Cr[pj]) - 128
+ pru := (pyy1 + 91881*pcr1) >> 8
+ pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
+ pbu := (pyy1 + 116130*pcb1) >> 8
+ if pru < 0 {
+ pru = 0
+ } else if pru > 0xffff {
+ pru = 0xffff
+ }
+ if pgu < 0 {
+ pgu = 0
+ } else if pgu > 0xffff {
+ pgu = 0xffff
+ }
+ if pbu < 0 {
+ pbu = 0
+ } else if pbu > 0xffff {
+ pbu = 0xffff
+ }
- // TODO: adjust the bias so that we can use int(f) instead
- // of math.Floor(f) and math.Ceil(f).
- sx += float64(bias.X)
- sx -= 0.5
- ix := int(math.Floor(sx - xHalfWidth))
- if ix < sr.Min.X {
- ix = sr.Min.X
+ pr += float64(pru) * c.weight
+ pg += float64(pgu) * c.weight
+ pb += float64(pbu) * c.weight
}
- jx := int(math.Ceil(sx + xHalfWidth))
- if jx > sr.Max.X {
- jx = sr.Max.X
+ tmp[t] = [4]float64{
+ pr * s.invTotalWeightFFFF,
+ pg * s.invTotalWeightFFFF,
+ pb * s.invTotalWeightFFFF,
+ 1,
}
+ t++
+ }
+ }
+}
- totalXWeight := 0.0
- for kx := ix; kx < jx; kx++ {
- xWeight := 0.0
- if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
- xWeight = q.At(t)
- }
- xWeights[kx-ix] = xWeight
- totalXWeight += xWeight
+func (z *kernelScaler) scaleX_Image(tmp [][4]float64, src image.Image, sr image.Rectangle) {
+ t := 0
+ for y := int32(0); y < z.sh; y++ {
+ for _, s := range z.horizontal.sources {
+ var pr, pg, pb, pa float64
+ for _, c := range z.horizontal.contribs[s.i:s.j] {
+ pru, pgu, pbu, pau := src.At(sr.Min.X+int(c.coord), sr.Min.Y+int(y)).RGBA()
+ pr += float64(pru) * c.weight
+ pg += float64(pgu) * c.weight
+ pb += float64(pbu) * c.weight
+ pa += float64(pau) * c.weight
}
- for x := range xWeights[:jx-ix] {
- xWeights[x] /= totalXWeight
+ tmp[t] = [4]float64{
+ pr * s.invTotalWeightFFFF,
+ pg * s.invTotalWeightFFFF,
+ pb * s.invTotalWeightFFFF,
+ pa * s.invTotalWeightFFFF,
}
+ t++
+ }
+ }
+}
- sy += float64(bias.Y)
- sy -= 0.5
- iy := int(math.Floor(sy - yHalfWidth))
- if iy < sr.Min.Y {
- iy = sr.Min.Y
+func (z *kernelScaler) scaleY_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, tmp [][4]float64) {
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ d := (dr.Min.Y+adr.Min.Y-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+int(dx)-dst.Rect.Min.X)*4
+ for _, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
+ var pr, pg, pb, pa float64
+ for _, c := range z.vertical.contribs[s.i:s.j] {
+ p := &tmp[c.coord*z.dw+dx]
+ pr += p[0] * c.weight
+ pg += p[1] * c.weight
+ pb += p[2] * c.weight
+ pa += p[3] * c.weight
}
- jy := int(math.Ceil(sy + yHalfWidth))
- if jy > sr.Max.Y {
- jy = sr.Max.Y
+ dst.Pix[d+0] = uint8(ftou(pr*s.invTotalWeight) >> 8)
+ dst.Pix[d+1] = uint8(ftou(pg*s.invTotalWeight) >> 8)
+ dst.Pix[d+2] = uint8(ftou(pb*s.invTotalWeight) >> 8)
+ dst.Pix[d+3] = uint8(ftou(pa*s.invTotalWeight) >> 8)
+ d += dst.Stride
+ }
+ }
+}
+
+func (z *kernelScaler) scaleY_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, tmp [][4]float64) {
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ d := (dr.Min.Y+adr.Min.Y-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+int(dx)-dst.Rect.Min.X)*4
+ for _, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
+ var pr, pg, pb, pa float64
+ for _, c := range z.vertical.contribs[s.i:s.j] {
+ p := &tmp[c.coord*z.dw+dx]
+ pr += p[0] * c.weight
+ pg += p[1] * c.weight
+ pb += p[2] * c.weight
+ pa += p[3] * c.weight
}
+ dst.Pix[d+0] = uint8(ftou(pr*s.invTotalWeight) >> 8)
+ dst.Pix[d+1] = uint8(ftou(pg*s.invTotalWeight) >> 8)
+ dst.Pix[d+2] = uint8(ftou(pb*s.invTotalWeight) >> 8)
+ dst.Pix[d+3] = uint8(ftou(pa*s.invTotalWeight) >> 8)
+ d += dst.Stride
+ }
+ }
+}
- totalYWeight := 0.0
- for ky := iy; ky < jy; ky++ {
- yWeight := 0.0
- if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
- yWeight = q.At(t)
- }
- yWeights[ky-iy] = yWeight
- totalYWeight += yWeight
- }
- for y := range yWeights[:jy-iy] {
- yWeights[y] /= totalYWeight
+func (z *kernelScaler) scaleY_Image_Over(dst Image, dr, adr image.Rectangle, tmp [][4]float64) {
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ for dy, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
+ var pr, pg, pb, pa float64
+ for _, c := range z.vertical.contribs[s.i:s.j] {
+ p := &tmp[c.coord*z.dw+dx]
+ pr += p[0] * c.weight
+ pg += p[1] * c.weight
+ pb += p[2] * c.weight
+ pa += p[3] * c.weight
}
+ dstColorRGBA64.R = ftou(pr * s.invTotalWeight)
+ dstColorRGBA64.G = ftou(pg * s.invTotalWeight)
+ dstColorRGBA64.B = ftou(pb * s.invTotalWeight)
+ dstColorRGBA64.A = ftou(pa * s.invTotalWeight)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColor)
+ }
+ }
+}
+func (z *kernelScaler) scaleY_Image_Src(dst Image, dr, adr image.Rectangle, tmp [][4]float64) {
+ dstColorRGBA64 := &color.RGBA64{}
+ dstColor := color.Color(dstColorRGBA64)
+ for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
+ for dy, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
var pr, pg, pb, pa float64
- for ky := iy; ky < jy; ky++ {
- if yWeight := yWeights[ky-iy]; yWeight != 0 {
- for kx := ix; kx < jx; kx++ {
- if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
- pru := uint32(src.Pix[pi+0]) * 0x101
- pgu := uint32(src.Pix[pi+1]) * 0x101
- pbu := uint32(src.Pix[pi+2]) * 0x101
- pau := uint32(src.Pix[pi+3]) * 0x101
- pr += float64(pru) * w
- pg += float64(pgu) * w
- pb += float64(pbu) * w
- pa += float64(pau) * w
- }
- }
- }
+ for _, c := range z.vertical.contribs[s.i:s.j] {
+ p := &tmp[c.coord*z.dw+dx]
+ pr += p[0] * c.weight
+ pg += p[1] * c.weight
+ pb += p[2] * c.weight
+ pa += p[3] * c.weight
}
- dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
- dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
- dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
- dst.Pix[d+3] = uint8(fffftou(pa) >> 8)
+ dstColorRGBA64.R = ftou(pr * s.invTotalWeight)
+ dstColorRGBA64.G = ftou(pg * s.invTotalWeight)
+ dstColorRGBA64.B = ftou(pb * s.invTotalWeight)
+ dstColorRGBA64.A = ftou(pa * s.invTotalWeight)
+ dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColor)
}
}
}
-func (q *Kernel) transform_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64) {
+func (q *Kernel) transform_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point, xscale, yscale float64) {
// When shrinking, broaden the effective kernel support so that we still
// visit every source pixel.
xHalfWidth, xKernelArgScale := q.Support, 1.0
@@ -7105,33 +4646,28 @@ func (q *Kernel) transform_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangl
yWeights[y] /= totalYWeight
}
- var pr, pg, pb, pa float64
+ var pr float64
for ky := iy; ky < jy; ky++ {
if yWeight := yWeights[ky-iy]; yWeight != 0 {
for kx := ix; kx < jx; kx++ {
if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
- pru := uint32(src.Pix[pi+0]) * 0x101
- pgu := uint32(src.Pix[pi+1]) * 0x101
- pbu := uint32(src.Pix[pi+2]) * 0x101
- pau := uint32(src.Pix[pi+3]) * 0x101
+ pi := (ky-src.Rect.Min.Y)*src.Stride + (kx - src.Rect.Min.X)
+ pru := uint32(src.Pix[pi]) * 0x101
pr += float64(pru) * w
- pg += float64(pgu) * w
- pb += float64(pbu) * w
- pa += float64(pau) * w
}
}
}
}
- dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
- dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
- dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
- dst.Pix[d+3] = uint8(fffftou(pa) >> 8)
+ out := uint8(fffftou(pr) >> 8)
+ dst.Pix[d+0] = out
+ dst.Pix[d+1] = out
+ dst.Pix[d+2] = out
+ dst.Pix[d+3] = 0xff
}
}
}
-func (q *Kernel) transform_RGBA_YCbCr444_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, xscale, yscale float64) {
+func (q *Kernel) transform_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64) {
// When shrinking, broaden the effective kernel support so that we still
// visit every source pixel.
xHalfWidth, xKernelArgScale := q.Support, 1.0
@@ -7209,40 +4745,20 @@ func (q *Kernel) transform_RGBA_YCbCr444_Over(dst *image.RGBA, dr, adr image.Rec
yWeights[y] /= totalYWeight
}
- var pr, pg, pb float64
+ var pr, pg, pb, pa float64
for ky := iy; ky < jy; ky++ {
if yWeight := yWeights[ky-iy]; yWeight != 0 {
for kx := ix; kx < jx; kx++ {
if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X)
- pj := (ky-src.Rect.Min.Y)*src.CStride + (kx - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi])<<16 + 1<<15
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pru := (pyy1 + 91881*pcr1) >> 8
- pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pbu := (pyy1 + 116130*pcb1) >> 8
- if pru < 0 {
- pru = 0
- } else if pru > 0xffff {
- pru = 0xffff
- }
- if pgu < 0 {
- pgu = 0
- } else if pgu > 0xffff {
- pgu = 0xffff
- }
- if pbu < 0 {
- pbu = 0
- } else if pbu > 0xffff {
- pbu = 0xffff
- }
-
+ pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
+ pau := uint32(src.Pix[pi+3]) * 0x101
+ pru := uint32(src.Pix[pi+0]) * pau / 0xff
+ pgu := uint32(src.Pix[pi+1]) * pau / 0xff
+ pbu := uint32(src.Pix[pi+2]) * pau / 0xff
pr += float64(pru) * w
pg += float64(pgu) * w
pb += float64(pbu) * w
+ pa += float64(pau) * w
}
}
}
@@ -7250,12 +4766,12 @@ func (q *Kernel) transform_RGBA_YCbCr444_Over(dst *image.RGBA, dr, adr image.Rec
dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
- dst.Pix[d+3] = 0xff
+ dst.Pix[d+3] = uint8(fffftou(pa) >> 8)
}
}
}
-func (q *Kernel) transform_RGBA_YCbCr422_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, xscale, yscale float64) {
+func (q *Kernel) transform_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64) {
// When shrinking, broaden the effective kernel support so that we still
// visit every source pixel.
xHalfWidth, xKernelArgScale := q.Support, 1.0
@@ -7333,40 +4849,20 @@ func (q *Kernel) transform_RGBA_YCbCr422_Over(dst *image.RGBA, dr, adr image.Rec
yWeights[y] /= totalYWeight
}
- var pr, pg, pb float64
+ var pr, pg, pb, pa float64
for ky := iy; ky < jy; ky++ {
if yWeight := yWeights[ky-iy]; yWeight != 0 {
for kx := ix; kx < jx; kx++ {
if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X)
- pj := (ky-src.Rect.Min.Y)*src.CStride + ((kx)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi])<<16 + 1<<15
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pru := (pyy1 + 91881*pcr1) >> 8
- pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pbu := (pyy1 + 116130*pcb1) >> 8
- if pru < 0 {
- pru = 0
- } else if pru > 0xffff {
- pru = 0xffff
- }
- if pgu < 0 {
- pgu = 0
- } else if pgu > 0xffff {
- pgu = 0xffff
- }
- if pbu < 0 {
- pbu = 0
- } else if pbu > 0xffff {
- pbu = 0xffff
- }
-
+ pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
+ pau := uint32(src.Pix[pi+3]) * 0x101
+ pru := uint32(src.Pix[pi+0]) * pau / 0xff
+ pgu := uint32(src.Pix[pi+1]) * pau / 0xff
+ pbu := uint32(src.Pix[pi+2]) * pau / 0xff
pr += float64(pru) * w
pg += float64(pgu) * w
pb += float64(pbu) * w
+ pa += float64(pau) * w
}
}
}
@@ -7374,12 +4870,12 @@ func (q *Kernel) transform_RGBA_YCbCr422_Over(dst *image.RGBA, dr, adr image.Rec
dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
- dst.Pix[d+3] = 0xff
+ dst.Pix[d+3] = uint8(fffftou(pa) >> 8)
}
}
}
-func (q *Kernel) transform_RGBA_YCbCr420_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, xscale, yscale float64) {
+func (q *Kernel) transform_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64) {
// When shrinking, broaden the effective kernel support so that we still
// visit every source pixel.
xHalfWidth, xKernelArgScale := q.Support, 1.0
@@ -7457,40 +4953,20 @@ func (q *Kernel) transform_RGBA_YCbCr420_Over(dst *image.RGBA, dr, adr image.Rec
yWeights[y] /= totalYWeight
}
- var pr, pg, pb float64
+ var pr, pg, pb, pa float64
for ky := iy; ky < jy; ky++ {
if yWeight := yWeights[ky-iy]; yWeight != 0 {
for kx := ix; kx < jx; kx++ {
if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X)
- pj := ((ky)/2-src.Rect.Min.Y/2)*src.CStride + ((kx)/2 - src.Rect.Min.X/2)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi])<<16 + 1<<15
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pru := (pyy1 + 91881*pcr1) >> 8
- pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pbu := (pyy1 + 116130*pcb1) >> 8
- if pru < 0 {
- pru = 0
- } else if pru > 0xffff {
- pru = 0xffff
- }
- if pgu < 0 {
- pgu = 0
- } else if pgu > 0xffff {
- pgu = 0xffff
- }
- if pbu < 0 {
- pbu = 0
- } else if pbu > 0xffff {
- pbu = 0xffff
- }
-
+ pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
+ pru := uint32(src.Pix[pi+0]) * 0x101
+ pgu := uint32(src.Pix[pi+1]) * 0x101
+ pbu := uint32(src.Pix[pi+2]) * 0x101
+ pau := uint32(src.Pix[pi+3]) * 0x101
pr += float64(pru) * w
pg += float64(pgu) * w
pb += float64(pbu) * w
+ pa += float64(pau) * w
}
}
}
@@ -7498,12 +4974,12 @@ func (q *Kernel) transform_RGBA_YCbCr420_Over(dst *image.RGBA, dr, adr image.Rec
dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
- dst.Pix[d+3] = 0xff
+ dst.Pix[d+3] = uint8(fffftou(pa) >> 8)
}
}
}
-func (q *Kernel) transform_RGBA_YCbCr440_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, xscale, yscale float64) {
+func (q *Kernel) transform_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64) {
// When shrinking, broaden the effective kernel support so that we still
// visit every source pixel.
xHalfWidth, xKernelArgScale := q.Support, 1.0
@@ -7581,40 +5057,20 @@ func (q *Kernel) transform_RGBA_YCbCr440_Over(dst *image.RGBA, dr, adr image.Rec
yWeights[y] /= totalYWeight
}
- var pr, pg, pb float64
+ var pr, pg, pb, pa float64
for ky := iy; ky < jy; ky++ {
if yWeight := yWeights[ky-iy]; yWeight != 0 {
for kx := ix; kx < jx; kx++ {
if w := xWeights[kx-ix] * yWeight; w != 0 {
- pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X)
- pj := ((ky)/2-src.Rect.Min.Y/2)*src.CStride + (kx - src.Rect.Min.X)
-
- // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
- pyy1 := int(src.Y[pi])<<16 + 1<<15
- pcb1 := int(src.Cb[pj]) - 128
- pcr1 := int(src.Cr[pj]) - 128
- pru := (pyy1 + 91881*pcr1) >> 8
- pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
- pbu := (pyy1 + 116130*pcb1) >> 8
- if pru < 0 {
- pru = 0
- } else if pru > 0xffff {
- pru = 0xffff
- }
- if pgu < 0 {
- pgu = 0
- } else if pgu > 0xffff {
- pgu = 0xffff
- }
- if pbu < 0 {
- pbu = 0
- } else if pbu > 0xffff {
- pbu = 0xffff
- }
-
+ pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
+ pru := uint32(src.Pix[pi+0]) * 0x101
+ pgu := uint32(src.Pix[pi+1]) * 0x101
+ pbu := uint32(src.Pix[pi+2]) * 0x101
+ pau := uint32(src.Pix[pi+3]) * 0x101
pr += float64(pru) * w
pg += float64(pgu) * w
pb += float64(pbu) * w
+ pa += float64(pau) * w
}
}
}
@@ -7622,7 +5078,7 @@ func (q *Kernel) transform_RGBA_YCbCr440_Over(dst *image.RGBA, dr, adr image.Rec
dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
- dst.Pix[d+3] = 0xff
+ dst.Pix[d+3] = uint8(fffftou(pa) >> 8)
}
}
}
diff --git a/draw/scale.go b/draw/scale.go
index 39520f4..00ef1d3 100644
--- a/draw/scale.go
+++ b/draw/scale.go
@@ -431,3 +431,10 @@ func transform_Uniform(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src *i
}
}
}
+
+func opaque(m image.Image) bool {
+ o, ok := m.(interface {
+ Opaque() bool
+ })
+ return ok && o.Opaque()
+}