draw: implement dstMask.
Change-Id: Id63695c3cef67fbe79fa1fbe916b85108f401093 Reviewed-on: https://go-review.googlesource.com/9191 Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
parent
76b4869e5a
commit
3940ddb240
77
draw/gen.go
77
draw/gen.go
|
@ -233,6 +233,7 @@ func expnDollar(prefix, dollar, suffix string, d *data) string {
|
||||||
return ";"
|
return ";"
|
||||||
case "Image":
|
case "Image":
|
||||||
return "" +
|
return "" +
|
||||||
|
"dstMask, dmp := opts.DstMask, opts.DstMaskP\n" +
|
||||||
"dstColorRGBA64 := &color.RGBA64{}\n" +
|
"dstColorRGBA64 := &color.RGBA64{}\n" +
|
||||||
"dstColor := color.Color(dstColorRGBA64)"
|
"dstColor := color.Color(dstColorRGBA64)"
|
||||||
}
|
}
|
||||||
|
@ -336,6 +337,13 @@ func expnDollar(prefix, dollar, suffix string, d *data) string {
|
||||||
case "Image":
|
case "Image":
|
||||||
return argf(args, ""+
|
return argf(args, ""+
|
||||||
"qr, qg, qb, qa := dst.At($0, $1).RGBA()\n"+
|
"qr, qg, qb, qa := dst.At($0, $1).RGBA()\n"+
|
||||||
|
"if dstMask != nil {\n"+
|
||||||
|
" _, _, _, ma := dstMask.At(dmp.X + $0, dmp.Y + $1).RGBA()\n"+
|
||||||
|
" $2r = $2r * ma / 0xffff\n"+
|
||||||
|
" $2g = $2g * ma / 0xffff\n"+
|
||||||
|
" $2b = $2b * ma / 0xffff\n"+
|
||||||
|
" $2a = $2a * ma / 0xffff\n"+
|
||||||
|
"}\n"+
|
||||||
"$2a1 := 0xffff - $2a\n"+
|
"$2a1 := 0xffff - $2a\n"+
|
||||||
"dstColorRGBA64.R = uint16(qr*$2a1/0xffff + $2r)\n"+
|
"dstColorRGBA64.R = uint16(qr*$2a1/0xffff + $2r)\n"+
|
||||||
"dstColorRGBA64.G = uint16(qg*$2a1/0xffff + $2g)\n"+
|
"dstColorRGBA64.G = uint16(qg*$2a1/0xffff + $2g)\n"+
|
||||||
|
@ -361,11 +369,26 @@ func expnDollar(prefix, dollar, suffix string, d *data) string {
|
||||||
switch d.sType {
|
switch d.sType {
|
||||||
default:
|
default:
|
||||||
return argf(args, ""+
|
return argf(args, ""+
|
||||||
"dstColorRGBA64.R = uint16($2r)\n"+
|
"if dstMask != nil {\n"+
|
||||||
"dstColorRGBA64.G = uint16($2g)\n"+
|
" qr, qg, qb, qa := dst.At($0, $1).RGBA()\n"+
|
||||||
"dstColorRGBA64.B = uint16($2b)\n"+
|
" _, _, _, ma := dstMask.At(dmp.X + $0, dmp.Y + $1).RGBA()\n"+
|
||||||
"dstColorRGBA64.A = uint16($2a)\n"+
|
" pr = pr * ma / 0xffff\n"+
|
||||||
"dst.Set($0, $1, dstColor)",
|
" pg = pg * ma / 0xffff\n"+
|
||||||
|
" pb = pb * ma / 0xffff\n"+
|
||||||
|
" pa = pa * ma / 0xffff\n"+
|
||||||
|
" $2a1 := 0xffff - ma\n"+ // Note that this is ma, not $2a.
|
||||||
|
" dstColorRGBA64.R = uint16(qr*$2a1/0xffff + $2r)\n"+
|
||||||
|
" dstColorRGBA64.G = uint16(qg*$2a1/0xffff + $2g)\n"+
|
||||||
|
" dstColorRGBA64.B = uint16(qb*$2a1/0xffff + $2b)\n"+
|
||||||
|
" dstColorRGBA64.A = uint16(qa*$2a1/0xffff + $2a)\n"+
|
||||||
|
" dst.Set($0, $1, dstColor)\n"+
|
||||||
|
"} else {\n"+
|
||||||
|
" dstColorRGBA64.R = uint16($2r)\n"+
|
||||||
|
" dstColorRGBA64.G = uint16($2g)\n"+
|
||||||
|
" dstColorRGBA64.B = uint16($2b)\n"+
|
||||||
|
" dstColorRGBA64.A = uint16($2a)\n"+
|
||||||
|
" dst.Set($0, $1, dstColor)\n"+
|
||||||
|
"}",
|
||||||
)
|
)
|
||||||
case "*image.Gray":
|
case "*image.Gray":
|
||||||
return argf(args, ""+
|
return argf(args, ""+
|
||||||
|
@ -432,6 +455,13 @@ func expnDollar(prefix, dollar, suffix string, d *data) string {
|
||||||
"$3g0 := uint32($2($3g * $4))\n"+
|
"$3g0 := uint32($2($3g * $4))\n"+
|
||||||
"$3b0 := uint32($2($3b * $4))\n"+
|
"$3b0 := uint32($2($3b * $4))\n"+
|
||||||
"$3a0 := uint32($2($3a * $4))\n"+
|
"$3a0 := uint32($2($3a * $4))\n"+
|
||||||
|
"if dstMask != nil {\n"+
|
||||||
|
" _, _, _, ma := dstMask.At(dmp.X + $0, dmp.Y + $1).RGBA()\n"+
|
||||||
|
" $3r0 = $3r0 * ma / 0xffff\n"+
|
||||||
|
" $3g0 = $3g0 * ma / 0xffff\n"+
|
||||||
|
" $3b0 = $3b0 * ma / 0xffff\n"+
|
||||||
|
" $3a0 = $3a0 * ma / 0xffff\n"+
|
||||||
|
"}\n"+
|
||||||
"$3a1 := 0xffff - $3a0\n"+
|
"$3a1 := 0xffff - $3a0\n"+
|
||||||
"dstColorRGBA64.R = uint16(qr*$3a1/0xffff + $3r0)\n"+
|
"dstColorRGBA64.R = uint16(qr*$3a1/0xffff + $3r0)\n"+
|
||||||
"dstColorRGBA64.G = uint16(qg*$3a1/0xffff + $3g0)\n"+
|
"dstColorRGBA64.G = uint16(qg*$3a1/0xffff + $3g0)\n"+
|
||||||
|
@ -461,11 +491,26 @@ func expnDollar(prefix, dollar, suffix string, d *data) string {
|
||||||
switch d.sType {
|
switch d.sType {
|
||||||
default:
|
default:
|
||||||
ret = argf(args, ""+
|
ret = argf(args, ""+
|
||||||
"dstColorRGBA64.R = $2($3r * $4)\n"+
|
"if dstMask != nil {\n"+
|
||||||
"dstColorRGBA64.G = $2($3g * $4)\n"+
|
" qr, qg, qb, qa := dst.At($0, $1).RGBA()\n"+
|
||||||
"dstColorRGBA64.B = $2($3b * $4)\n"+
|
" _, _, _, ma := dstMask.At(dmp.X + $0, dmp.Y + $1).RGBA()\n"+
|
||||||
"dstColorRGBA64.A = $2($3a * $4)\n"+
|
" pr := uint32($2($3r * $4)) * ma / 0xffff\n"+
|
||||||
"dst.Set($0, $1, dstColor)",
|
" pg := uint32($2($3g * $4)) * ma / 0xffff\n"+
|
||||||
|
" pb := uint32($2($3b * $4)) * ma / 0xffff\n"+
|
||||||
|
" pa := uint32($2($3a * $4)) * ma / 0xffff\n"+
|
||||||
|
" pa1 := 0xffff - ma\n"+ // Note that this is ma, not pa.
|
||||||
|
" dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)\n"+
|
||||||
|
" dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)\n"+
|
||||||
|
" dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)\n"+
|
||||||
|
" dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)\n"+
|
||||||
|
" dst.Set($0, $1, dstColor)\n"+
|
||||||
|
"} else {\n"+
|
||||||
|
" dstColorRGBA64.R = $2($3r * $4)\n"+
|
||||||
|
" dstColorRGBA64.G = $2($3g * $4)\n"+
|
||||||
|
" dstColorRGBA64.B = $2($3b * $4)\n"+
|
||||||
|
" dstColorRGBA64.A = $2($3a * $4)\n"+
|
||||||
|
" dst.Set($0, $1, dstColor)\n"+
|
||||||
|
"}",
|
||||||
)
|
)
|
||||||
case "*image.Gray":
|
case "*image.Gray":
|
||||||
ret = argf(args, ""+
|
ret = argf(args, ""+
|
||||||
|
@ -1130,8 +1175,16 @@ const (
|
||||||
$switchS z.scaleX_$sTypeRN$sratio(tmp, src, sr, &o)
|
$switchS z.scaleX_$sTypeRN$sratio(tmp, src, sr, &o)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: honor o.DstMask.
|
if o.DstMask != nil {
|
||||||
$switchD z.scaleY_$dTypeRN_$op(dst, dr, adr, tmp, &o)
|
switch o.Op {
|
||||||
|
case Over:
|
||||||
|
z.scaleY_Image_Over(dst, dr, adr, tmp, &o)
|
||||||
|
case Src:
|
||||||
|
z.scaleY_Image_Src(dst, dr, adr, tmp, &o)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$switchD z.scaleY_$dTypeRN_$op(dst, dr, adr, tmp, &o)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Kernel) Transform(dst Image, s2d *f64.Aff3, src image.Image, sr image.Rectangle, opts *Options) {
|
func (q *Kernel) Transform(dst Image, s2d *f64.Aff3, src image.Image, sr image.Rectangle, opts *Options) {
|
||||||
|
|
238
draw/impl.go
238
draw/impl.go
|
@ -527,6 +527,7 @@ func (nnInterpolator) scale_Image_Image_Over(dst Image, dr, adr image.Rectangle,
|
||||||
dh2 := uint64(dr.Dy()) * 2
|
dh2 := uint64(dr.Dy()) * 2
|
||||||
sw := uint64(sr.Dx())
|
sw := uint64(sr.Dx())
|
||||||
sh := uint64(sr.Dy())
|
sh := uint64(sr.Dy())
|
||||||
|
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||||
dstColorRGBA64 := &color.RGBA64{}
|
dstColorRGBA64 := &color.RGBA64{}
|
||||||
dstColor := color.Color(dstColorRGBA64)
|
dstColor := color.Color(dstColorRGBA64)
|
||||||
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
||||||
|
@ -535,6 +536,13 @@ func (nnInterpolator) scale_Image_Image_Over(dst Image, dr, adr image.Rectangle,
|
||||||
sx := (2*uint64(dx) + 1) * sw / dw2
|
sx := (2*uint64(dx) + 1) * sw / dw2
|
||||||
pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA()
|
pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA()
|
||||||
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
|
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
|
||||||
|
if dstMask != nil {
|
||||||
|
_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
|
||||||
|
pr = pr * ma / 0xffff
|
||||||
|
pg = pg * ma / 0xffff
|
||||||
|
pb = pb * ma / 0xffff
|
||||||
|
pa = pa * ma / 0xffff
|
||||||
|
}
|
||||||
pa1 := 0xffff - pa
|
pa1 := 0xffff - pa
|
||||||
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
|
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
|
||||||
dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
|
dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
|
||||||
|
@ -550,6 +558,7 @@ func (nnInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle,
|
||||||
dh2 := uint64(dr.Dy()) * 2
|
dh2 := uint64(dr.Dy()) * 2
|
||||||
sw := uint64(sr.Dx())
|
sw := uint64(sr.Dx())
|
||||||
sh := uint64(sr.Dy())
|
sh := uint64(sr.Dy())
|
||||||
|
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||||
dstColorRGBA64 := &color.RGBA64{}
|
dstColorRGBA64 := &color.RGBA64{}
|
||||||
dstColor := color.Color(dstColorRGBA64)
|
dstColor := color.Color(dstColorRGBA64)
|
||||||
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
||||||
|
@ -557,11 +566,26 @@ func (nnInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle,
|
||||||
for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
|
for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
|
||||||
sx := (2*uint64(dx) + 1) * sw / dw2
|
sx := (2*uint64(dx) + 1) * sw / dw2
|
||||||
pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA()
|
pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA()
|
||||||
dstColorRGBA64.R = uint16(pr)
|
if dstMask != nil {
|
||||||
dstColorRGBA64.G = uint16(pg)
|
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
|
||||||
dstColorRGBA64.B = uint16(pb)
|
_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
|
||||||
dstColorRGBA64.A = uint16(pa)
|
pr = pr * ma / 0xffff
|
||||||
dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
|
pg = pg * ma / 0xffff
|
||||||
|
pb = pb * ma / 0xffff
|
||||||
|
pa = pa * ma / 0xffff
|
||||||
|
pa1 := 0xffff - ma
|
||||||
|
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
|
||||||
|
dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
|
||||||
|
dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
|
||||||
|
dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
|
||||||
|
dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
|
||||||
|
} else {
|
||||||
|
dstColorRGBA64.R = uint16(pr)
|
||||||
|
dstColorRGBA64.G = uint16(pg)
|
||||||
|
dstColorRGBA64.B = uint16(pb)
|
||||||
|
dstColorRGBA64.A = uint16(pa)
|
||||||
|
dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -904,6 +928,7 @@ func (nnInterpolator) transform_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Re
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nnInterpolator) transform_Image_Image_Over(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
|
func (nnInterpolator) transform_Image_Image_Over(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
|
||||||
|
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||||
dstColorRGBA64 := &color.RGBA64{}
|
dstColorRGBA64 := &color.RGBA64{}
|
||||||
dstColor := color.Color(dstColorRGBA64)
|
dstColor := color.Color(dstColorRGBA64)
|
||||||
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
||||||
|
@ -917,6 +942,13 @@ func (nnInterpolator) transform_Image_Image_Over(dst Image, dr, adr image.Rectan
|
||||||
}
|
}
|
||||||
pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
|
pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
|
||||||
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
|
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
|
||||||
|
if dstMask != nil {
|
||||||
|
_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
|
||||||
|
pr = pr * ma / 0xffff
|
||||||
|
pg = pg * ma / 0xffff
|
||||||
|
pb = pb * ma / 0xffff
|
||||||
|
pa = pa * ma / 0xffff
|
||||||
|
}
|
||||||
pa1 := 0xffff - pa
|
pa1 := 0xffff - pa
|
||||||
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
|
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
|
||||||
dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
|
dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
|
||||||
|
@ -928,6 +960,7 @@ func (nnInterpolator) transform_Image_Image_Over(dst Image, dr, adr image.Rectan
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nnInterpolator) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
|
func (nnInterpolator) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
|
||||||
|
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||||
dstColorRGBA64 := &color.RGBA64{}
|
dstColorRGBA64 := &color.RGBA64{}
|
||||||
dstColor := color.Color(dstColorRGBA64)
|
dstColor := color.Color(dstColorRGBA64)
|
||||||
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
||||||
|
@ -940,11 +973,26 @@ func (nnInterpolator) transform_Image_Image_Src(dst Image, dr, adr image.Rectang
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
|
pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
|
||||||
dstColorRGBA64.R = uint16(pr)
|
if dstMask != nil {
|
||||||
dstColorRGBA64.G = uint16(pg)
|
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
|
||||||
dstColorRGBA64.B = uint16(pb)
|
_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
|
||||||
dstColorRGBA64.A = uint16(pa)
|
pr = pr * ma / 0xffff
|
||||||
dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
|
pg = pg * ma / 0xffff
|
||||||
|
pb = pb * ma / 0xffff
|
||||||
|
pa = pa * ma / 0xffff
|
||||||
|
pa1 := 0xffff - ma
|
||||||
|
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
|
||||||
|
dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
|
||||||
|
dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
|
||||||
|
dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
|
||||||
|
dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
|
||||||
|
} else {
|
||||||
|
dstColorRGBA64.R = uint16(pr)
|
||||||
|
dstColorRGBA64.G = uint16(pg)
|
||||||
|
dstColorRGBA64.B = uint16(pb)
|
||||||
|
dstColorRGBA64.A = uint16(pa)
|
||||||
|
dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2470,6 +2518,7 @@ func (ablInterpolator) scale_Image_Image_Over(dst Image, dr, adr image.Rectangle
|
||||||
yscale := float64(sh) / float64(dr.Dy())
|
yscale := float64(sh) / float64(dr.Dy())
|
||||||
xscale := float64(sw) / float64(dr.Dx())
|
xscale := float64(sw) / float64(dr.Dx())
|
||||||
swMinus1, shMinus1 := sw-1, sh-1
|
swMinus1, shMinus1 := sw-1, sh-1
|
||||||
|
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||||
dstColorRGBA64 := &color.RGBA64{}
|
dstColorRGBA64 := &color.RGBA64{}
|
||||||
dstColor := color.Color(dstColorRGBA64)
|
dstColor := color.Color(dstColorRGBA64)
|
||||||
|
|
||||||
|
@ -2541,6 +2590,13 @@ func (ablInterpolator) scale_Image_Image_Over(dst Image, dr, adr image.Rectangle
|
||||||
pb := uint32(s11b)
|
pb := uint32(s11b)
|
||||||
pa := uint32(s11a)
|
pa := uint32(s11a)
|
||||||
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
|
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
|
||||||
|
if dstMask != nil {
|
||||||
|
_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
|
||||||
|
pr = pr * ma / 0xffff
|
||||||
|
pg = pg * ma / 0xffff
|
||||||
|
pb = pb * ma / 0xffff
|
||||||
|
pa = pa * ma / 0xffff
|
||||||
|
}
|
||||||
pa1 := 0xffff - pa
|
pa1 := 0xffff - pa
|
||||||
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
|
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
|
||||||
dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
|
dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
|
||||||
|
@ -2557,6 +2613,7 @@ func (ablInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle,
|
||||||
yscale := float64(sh) / float64(dr.Dy())
|
yscale := float64(sh) / float64(dr.Dy())
|
||||||
xscale := float64(sw) / float64(dr.Dx())
|
xscale := float64(sw) / float64(dr.Dx())
|
||||||
swMinus1, shMinus1 := sw-1, sh-1
|
swMinus1, shMinus1 := sw-1, sh-1
|
||||||
|
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||||
dstColorRGBA64 := &color.RGBA64{}
|
dstColorRGBA64 := &color.RGBA64{}
|
||||||
dstColor := color.Color(dstColorRGBA64)
|
dstColor := color.Color(dstColorRGBA64)
|
||||||
|
|
||||||
|
@ -2627,11 +2684,26 @@ func (ablInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle,
|
||||||
pg := uint32(s11g)
|
pg := uint32(s11g)
|
||||||
pb := uint32(s11b)
|
pb := uint32(s11b)
|
||||||
pa := uint32(s11a)
|
pa := uint32(s11a)
|
||||||
dstColorRGBA64.R = uint16(pr)
|
if dstMask != nil {
|
||||||
dstColorRGBA64.G = uint16(pg)
|
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
|
||||||
dstColorRGBA64.B = uint16(pb)
|
_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
|
||||||
dstColorRGBA64.A = uint16(pa)
|
pr = pr * ma / 0xffff
|
||||||
dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
|
pg = pg * ma / 0xffff
|
||||||
|
pb = pb * ma / 0xffff
|
||||||
|
pa = pa * ma / 0xffff
|
||||||
|
pa1 := 0xffff - ma
|
||||||
|
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
|
||||||
|
dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
|
||||||
|
dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
|
||||||
|
dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
|
||||||
|
dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
|
||||||
|
} else {
|
||||||
|
dstColorRGBA64.R = uint16(pr)
|
||||||
|
dstColorRGBA64.G = uint16(pg)
|
||||||
|
dstColorRGBA64.B = uint16(pb)
|
||||||
|
dstColorRGBA64.A = uint16(pa)
|
||||||
|
dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3977,6 +4049,7 @@ func (ablInterpolator) transform_RGBA_Image_Src(dst *image.RGBA, dr, adr image.R
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ablInterpolator) transform_Image_Image_Over(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
|
func (ablInterpolator) transform_Image_Image_Over(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
|
||||||
|
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||||
dstColorRGBA64 := &color.RGBA64{}
|
dstColorRGBA64 := &color.RGBA64{}
|
||||||
dstColor := color.Color(dstColorRGBA64)
|
dstColor := color.Color(dstColorRGBA64)
|
||||||
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
||||||
|
@ -4054,6 +4127,13 @@ func (ablInterpolator) transform_Image_Image_Over(dst Image, dr, adr image.Recta
|
||||||
pb := uint32(s11b)
|
pb := uint32(s11b)
|
||||||
pa := uint32(s11a)
|
pa := uint32(s11a)
|
||||||
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
|
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
|
||||||
|
if dstMask != nil {
|
||||||
|
_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
|
||||||
|
pr = pr * ma / 0xffff
|
||||||
|
pg = pg * ma / 0xffff
|
||||||
|
pb = pb * ma / 0xffff
|
||||||
|
pa = pa * ma / 0xffff
|
||||||
|
}
|
||||||
pa1 := 0xffff - pa
|
pa1 := 0xffff - pa
|
||||||
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
|
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
|
||||||
dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
|
dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
|
||||||
|
@ -4065,6 +4145,7 @@ func (ablInterpolator) transform_Image_Image_Over(dst Image, dr, adr image.Recta
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ablInterpolator) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
|
func (ablInterpolator) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
|
||||||
|
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||||
dstColorRGBA64 := &color.RGBA64{}
|
dstColorRGBA64 := &color.RGBA64{}
|
||||||
dstColor := color.Color(dstColorRGBA64)
|
dstColor := color.Color(dstColorRGBA64)
|
||||||
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
||||||
|
@ -4141,11 +4222,26 @@ func (ablInterpolator) transform_Image_Image_Src(dst Image, dr, adr image.Rectan
|
||||||
pg := uint32(s11g)
|
pg := uint32(s11g)
|
||||||
pb := uint32(s11b)
|
pb := uint32(s11b)
|
||||||
pa := uint32(s11a)
|
pa := uint32(s11a)
|
||||||
dstColorRGBA64.R = uint16(pr)
|
if dstMask != nil {
|
||||||
dstColorRGBA64.G = uint16(pg)
|
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
|
||||||
dstColorRGBA64.B = uint16(pb)
|
_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
|
||||||
dstColorRGBA64.A = uint16(pa)
|
pr = pr * ma / 0xffff
|
||||||
dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
|
pg = pg * ma / 0xffff
|
||||||
|
pb = pb * ma / 0xffff
|
||||||
|
pa = pa * ma / 0xffff
|
||||||
|
pa1 := 0xffff - ma
|
||||||
|
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
|
||||||
|
dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
|
||||||
|
dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
|
||||||
|
dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
|
||||||
|
dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
|
||||||
|
} else {
|
||||||
|
dstColorRGBA64.R = uint16(pr)
|
||||||
|
dstColorRGBA64.G = uint16(pg)
|
||||||
|
dstColorRGBA64.B = uint16(pb)
|
||||||
|
dstColorRGBA64.A = uint16(pa)
|
||||||
|
dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4221,22 +4317,30 @@ func (z *kernelScaler) Scale(dst Image, dr image.Rectangle, src image.Image, sr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: honor o.DstMask.
|
if o.DstMask != nil {
|
||||||
switch o.Op {
|
switch o.Op {
|
||||||
case Over:
|
case Over:
|
||||||
switch dst := dst.(type) {
|
|
||||||
case *image.RGBA:
|
|
||||||
z.scaleY_RGBA_Over(dst, dr, adr, tmp, &o)
|
|
||||||
default:
|
|
||||||
z.scaleY_Image_Over(dst, dr, adr, tmp, &o)
|
z.scaleY_Image_Over(dst, dr, adr, tmp, &o)
|
||||||
}
|
case Src:
|
||||||
case Src:
|
|
||||||
switch dst := dst.(type) {
|
|
||||||
case *image.RGBA:
|
|
||||||
z.scaleY_RGBA_Src(dst, dr, adr, tmp, &o)
|
|
||||||
default:
|
|
||||||
z.scaleY_Image_Src(dst, dr, adr, tmp, &o)
|
z.scaleY_Image_Src(dst, dr, adr, tmp, &o)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
switch o.Op {
|
||||||
|
case Over:
|
||||||
|
switch dst := dst.(type) {
|
||||||
|
case *image.RGBA:
|
||||||
|
z.scaleY_RGBA_Over(dst, dr, adr, tmp, &o)
|
||||||
|
default:
|
||||||
|
z.scaleY_Image_Over(dst, dr, adr, tmp, &o)
|
||||||
|
}
|
||||||
|
case Src:
|
||||||
|
switch dst := dst.(type) {
|
||||||
|
case *image.RGBA:
|
||||||
|
z.scaleY_RGBA_Src(dst, dr, adr, tmp, &o)
|
||||||
|
default:
|
||||||
|
z.scaleY_Image_Src(dst, dr, adr, tmp, &o)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4710,6 +4814,7 @@ func (z *kernelScaler) scaleY_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (z *kernelScaler) scaleY_Image_Over(dst Image, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
|
func (z *kernelScaler) scaleY_Image_Over(dst Image, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
|
||||||
|
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||||
dstColorRGBA64 := &color.RGBA64{}
|
dstColorRGBA64 := &color.RGBA64{}
|
||||||
dstColor := color.Color(dstColorRGBA64)
|
dstColor := color.Color(dstColorRGBA64)
|
||||||
for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
|
for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
|
||||||
|
@ -4738,6 +4843,13 @@ func (z *kernelScaler) scaleY_Image_Over(dst Image, dr, adr image.Rectangle, tmp
|
||||||
pg0 := uint32(ftou(pg * s.invTotalWeight))
|
pg0 := uint32(ftou(pg * s.invTotalWeight))
|
||||||
pb0 := uint32(ftou(pb * s.invTotalWeight))
|
pb0 := uint32(ftou(pb * s.invTotalWeight))
|
||||||
pa0 := uint32(ftou(pa * s.invTotalWeight))
|
pa0 := uint32(ftou(pa * s.invTotalWeight))
|
||||||
|
if dstMask != nil {
|
||||||
|
_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
|
||||||
|
pr0 = pr0 * ma / 0xffff
|
||||||
|
pg0 = pg0 * ma / 0xffff
|
||||||
|
pb0 = pb0 * ma / 0xffff
|
||||||
|
pa0 = pa0 * ma / 0xffff
|
||||||
|
}
|
||||||
pa1 := 0xffff - pa0
|
pa1 := 0xffff - pa0
|
||||||
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr0)
|
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr0)
|
||||||
dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg0)
|
dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg0)
|
||||||
|
@ -4749,6 +4861,7 @@ func (z *kernelScaler) scaleY_Image_Over(dst Image, dr, adr image.Rectangle, tmp
|
||||||
}
|
}
|
||||||
|
|
||||||
func (z *kernelScaler) scaleY_Image_Src(dst Image, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
|
func (z *kernelScaler) scaleY_Image_Src(dst Image, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
|
||||||
|
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||||
dstColorRGBA64 := &color.RGBA64{}
|
dstColorRGBA64 := &color.RGBA64{}
|
||||||
dstColor := color.Color(dstColorRGBA64)
|
dstColor := color.Color(dstColorRGBA64)
|
||||||
for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
|
for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
|
||||||
|
@ -4772,11 +4885,26 @@ func (z *kernelScaler) scaleY_Image_Src(dst Image, dr, adr image.Rectangle, tmp
|
||||||
pb = pa
|
pb = pa
|
||||||
}
|
}
|
||||||
|
|
||||||
dstColorRGBA64.R = ftou(pr * s.invTotalWeight)
|
if dstMask != nil {
|
||||||
dstColorRGBA64.G = ftou(pg * s.invTotalWeight)
|
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
|
||||||
dstColorRGBA64.B = ftou(pb * s.invTotalWeight)
|
_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
|
||||||
dstColorRGBA64.A = ftou(pa * s.invTotalWeight)
|
pr := uint32(ftou(pr*s.invTotalWeight)) * ma / 0xffff
|
||||||
dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColor)
|
pg := uint32(ftou(pg*s.invTotalWeight)) * ma / 0xffff
|
||||||
|
pb := uint32(ftou(pb*s.invTotalWeight)) * ma / 0xffff
|
||||||
|
pa := uint32(ftou(pa*s.invTotalWeight)) * ma / 0xffff
|
||||||
|
pa1 := 0xffff - ma
|
||||||
|
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
|
||||||
|
dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
|
||||||
|
dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
|
||||||
|
dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
|
||||||
|
dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColor)
|
||||||
|
} else {
|
||||||
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6090,6 +6218,7 @@ func (q *Kernel) transform_Image_Image_Over(dst Image, dr, adr image.Rectangle,
|
||||||
xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
|
xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
|
||||||
yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
|
yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
|
||||||
|
|
||||||
|
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||||
dstColorRGBA64 := &color.RGBA64{}
|
dstColorRGBA64 := &color.RGBA64{}
|
||||||
dstColor := color.Color(dstColorRGBA64)
|
dstColor := color.Color(dstColorRGBA64)
|
||||||
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
||||||
|
@ -6182,6 +6311,13 @@ func (q *Kernel) transform_Image_Image_Over(dst Image, dr, adr image.Rectangle,
|
||||||
pg0 := uint32(fffftou(pg))
|
pg0 := uint32(fffftou(pg))
|
||||||
pb0 := uint32(fffftou(pb))
|
pb0 := uint32(fffftou(pb))
|
||||||
pa0 := uint32(fffftou(pa))
|
pa0 := uint32(fffftou(pa))
|
||||||
|
if dstMask != nil {
|
||||||
|
_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
|
||||||
|
pr0 = pr0 * ma / 0xffff
|
||||||
|
pg0 = pg0 * ma / 0xffff
|
||||||
|
pb0 = pb0 * ma / 0xffff
|
||||||
|
pa0 = pa0 * ma / 0xffff
|
||||||
|
}
|
||||||
pa1 := 0xffff - pa0
|
pa1 := 0xffff - pa0
|
||||||
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr0)
|
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr0)
|
||||||
dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg0)
|
dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg0)
|
||||||
|
@ -6209,6 +6345,7 @@ func (q *Kernel) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d
|
||||||
xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
|
xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
|
||||||
yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
|
yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
|
||||||
|
|
||||||
|
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||||
dstColorRGBA64 := &color.RGBA64{}
|
dstColorRGBA64 := &color.RGBA64{}
|
||||||
dstColor := color.Color(dstColorRGBA64)
|
dstColor := color.Color(dstColorRGBA64)
|
||||||
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
||||||
|
@ -6296,11 +6433,26 @@ func (q *Kernel) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d
|
||||||
pb = pa
|
pb = pa
|
||||||
}
|
}
|
||||||
|
|
||||||
dstColorRGBA64.R = fffftou(pr)
|
if dstMask != nil {
|
||||||
dstColorRGBA64.G = fffftou(pg)
|
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
|
||||||
dstColorRGBA64.B = fffftou(pb)
|
_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
|
||||||
dstColorRGBA64.A = fffftou(pa)
|
pr := uint32(fffftou(pr)) * ma / 0xffff
|
||||||
dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
|
pg := uint32(fffftou(pg)) * ma / 0xffff
|
||||||
|
pb := uint32(fffftou(pb)) * ma / 0xffff
|
||||||
|
pa := uint32(fffftou(pa)) * ma / 0xffff
|
||||||
|
pa1 := 0xffff - ma
|
||||||
|
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
|
||||||
|
dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
|
||||||
|
dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
|
||||||
|
dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
|
||||||
|
dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
|
||||||
|
} else {
|
||||||
|
dstColorRGBA64.R = fffftou(pr)
|
||||||
|
dstColorRGBA64.G = fffftou(pg)
|
||||||
|
dstColorRGBA64.B = fffftou(pb)
|
||||||
|
dstColorRGBA64.A = fffftou(pa)
|
||||||
|
dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,12 @@ func Copy(dst Image, dp image.Point, src image.Image, sr image.Rectangle, opts *
|
||||||
o = *opts
|
o = *opts
|
||||||
}
|
}
|
||||||
dr := sr.Add(dp.Sub(sr.Min))
|
dr := sr.Add(dp.Sub(sr.Min))
|
||||||
// TODO: honor o.DstMask and o.SrcMask.
|
if o.DstMask == nil {
|
||||||
DrawMask(dst, dr, src, sr.Min, nil, image.Point{}, o.Op)
|
// TODO: honor o.SrcMask.
|
||||||
|
DrawMask(dst, dr, src, sr.Min, nil, image.Point{}, o.Op)
|
||||||
|
} else {
|
||||||
|
NearestNeighbor.Scale(dst, dr, src, sr, opts)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scaler scales the part of the source image defined by src and sr and writes
|
// Scaler scales the part of the source image defined by src and sr and writes
|
||||||
|
@ -89,7 +93,7 @@ type Options struct {
|
||||||
DstMaskP image.Point
|
DstMaskP image.Point
|
||||||
SrcMask image.Image
|
SrcMask image.Image
|
||||||
SrcMaskP image.Point
|
SrcMaskP image.Point
|
||||||
// TODO: actually implement DstMask and SrcMask.
|
// TODO: actually implement SrcMask.
|
||||||
|
|
||||||
// TODO: a smooth vs sharp edges option, for arbitrary rotations?
|
// TODO: a smooth vs sharp edges option, for arbitrary rotations?
|
||||||
}
|
}
|
||||||
|
|
|
@ -316,6 +316,93 @@ func TestSrcTranslationInvariance(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDstMask(t *testing.T) {
|
||||||
|
dstMask := image.NewRGBA(image.Rect(0, 0, 23, 1))
|
||||||
|
dstMask.SetRGBA(19, 0, color.RGBA{0x00, 0x00, 0x00, 0x7f})
|
||||||
|
dstMask.SetRGBA(20, 0, color.RGBA{0x00, 0x00, 0x00, 0xff})
|
||||||
|
dstMask.SetRGBA(21, 0, color.RGBA{0x00, 0x00, 0x00, 0x3f})
|
||||||
|
dstMask.SetRGBA(22, 0, color.RGBA{0x00, 0x00, 0x00, 0x00})
|
||||||
|
red := image.NewRGBA(image.Rect(0, 0, 1, 1))
|
||||||
|
red.SetRGBA(0, 0, color.RGBA{0xff, 0x00, 0x00, 0xff})
|
||||||
|
blue := image.NewUniform(color.RGBA{0x00, 0x00, 0xff, 0xff})
|
||||||
|
qs := []Interpolator{
|
||||||
|
NearestNeighbor,
|
||||||
|
ApproxBiLinear,
|
||||||
|
CatmullRom,
|
||||||
|
}
|
||||||
|
for _, q := range qs {
|
||||||
|
dst := image.NewRGBA(image.Rect(0, 0, 3, 1))
|
||||||
|
Copy(dst, image.Point{}, blue, dst.Bounds(), nil)
|
||||||
|
q.Scale(dst, dst.Bounds(), red, red.Bounds(), &Options{
|
||||||
|
DstMask: dstMask,
|
||||||
|
DstMaskP: image.Point{20, 0},
|
||||||
|
})
|
||||||
|
got := [3]color.RGBA{
|
||||||
|
dst.RGBAAt(0, 0),
|
||||||
|
dst.RGBAAt(1, 0),
|
||||||
|
dst.RGBAAt(2, 0),
|
||||||
|
}
|
||||||
|
want := [3]color.RGBA{
|
||||||
|
{0xff, 0x00, 0x00, 0xff},
|
||||||
|
{0x3f, 0x00, 0xc0, 0xff},
|
||||||
|
{0x00, 0x00, 0xff, 0xff},
|
||||||
|
}
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("q=%T:\ngot %v\nwant %v", q, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRectDstMask(t *testing.T) {
|
||||||
|
f, err := os.Open("../testdata/testpattern.png")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Open: %v", err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
src, _, err := image.Decode(f)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Decode: %v", err)
|
||||||
|
}
|
||||||
|
m00 := transformMatrix(1, 0, 0)
|
||||||
|
|
||||||
|
bounds := image.Rect(0, 0, 50, 50)
|
||||||
|
dstOutside := image.NewRGBA(bounds)
|
||||||
|
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
|
||||||
|
for x := bounds.Min.X; x < bounds.Max.X; x++ {
|
||||||
|
dstOutside.SetRGBA(x, y, color.RGBA{uint8(5 * x), uint8(5 * y), 0x00, 0xff})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mk := func(q Transformer, dstMask image.Image) *image.RGBA {
|
||||||
|
m := image.NewRGBA(bounds)
|
||||||
|
Copy(m, bounds.Min, dstOutside, bounds, nil)
|
||||||
|
q.Transform(m, m00, src, src.Bounds(), &Options{DstMask: dstMask})
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
rect := image.Rect(20, 10, 30, 40)
|
||||||
|
qs := []Interpolator{
|
||||||
|
NearestNeighbor,
|
||||||
|
ApproxBiLinear,
|
||||||
|
CatmullRom,
|
||||||
|
}
|
||||||
|
for _, q := range qs {
|
||||||
|
dstInside := mk(q, nil)
|
||||||
|
dst := mk(q, rect)
|
||||||
|
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
|
||||||
|
for x := bounds.Min.X; x < bounds.Max.X; x++ {
|
||||||
|
which := dstOutside
|
||||||
|
if (image.Point{x, y}).In(rect) {
|
||||||
|
which = dstInside
|
||||||
|
}
|
||||||
|
if got, want := dst.RGBAAt(x, y), which.RGBAAt(x, y); got != want {
|
||||||
|
t.Errorf("x=%3d y=%3d: got %v, want %v", x, y, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The fooWrapper types wrap the dst or src image to avoid triggering the
|
// The fooWrapper types wrap the dst or src image to avoid triggering the
|
||||||
// type-specific fast path implementations.
|
// type-specific fast path implementations.
|
||||||
type (
|
type (
|
||||||
|
|
Loading…
Reference in New Issue
Block a user