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
59
draw/gen.go
59
draw/gen.go
|
@ -233,6 +233,7 @@ func expnDollar(prefix, dollar, suffix string, d *data) string {
|
|||
return ";"
|
||||
case "Image":
|
||||
return "" +
|
||||
"dstMask, dmp := opts.DstMask, opts.DstMaskP\n" +
|
||||
"dstColorRGBA64 := &color.RGBA64{}\n" +
|
||||
"dstColor := color.Color(dstColorRGBA64)"
|
||||
}
|
||||
|
@ -336,6 +337,13 @@ func expnDollar(prefix, dollar, suffix string, d *data) string {
|
|||
case "Image":
|
||||
return argf(args, ""+
|
||||
"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"+
|
||||
"dstColorRGBA64.R = uint16(qr*$2a1/0xffff + $2r)\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 {
|
||||
default:
|
||||
return argf(args, ""+
|
||||
"if dstMask != nil {\n"+
|
||||
" qr, qg, qb, qa := dst.At($0, $1).RGBA()\n"+
|
||||
" _, _, _, ma := dstMask.At(dmp.X + $0, dmp.Y + $1).RGBA()\n"+
|
||||
" pr = pr * ma / 0xffff\n"+
|
||||
" 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)",
|
||||
" dst.Set($0, $1, dstColor)\n"+
|
||||
"}",
|
||||
)
|
||||
case "*image.Gray":
|
||||
return argf(args, ""+
|
||||
|
@ -432,6 +455,13 @@ func expnDollar(prefix, dollar, suffix string, d *data) string {
|
|||
"$3g0 := uint32($2($3g * $4))\n"+
|
||||
"$3b0 := uint32($2($3b * $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"+
|
||||
"dstColorRGBA64.R = uint16(qr*$3a1/0xffff + $3r0)\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 {
|
||||
default:
|
||||
ret = argf(args, ""+
|
||||
"if dstMask != nil {\n"+
|
||||
" qr, qg, qb, qa := dst.At($0, $1).RGBA()\n"+
|
||||
" _, _, _, ma := dstMask.At(dmp.X + $0, dmp.Y + $1).RGBA()\n"+
|
||||
" pr := uint32($2($3r * $4)) * ma / 0xffff\n"+
|
||||
" 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)",
|
||||
" dst.Set($0, $1, dstColor)\n"+
|
||||
"}",
|
||||
)
|
||||
case "*image.Gray":
|
||||
ret = argf(args, ""+
|
||||
|
@ -1130,9 +1175,17 @@ const (
|
|||
$switchS z.scaleX_$sTypeRN$sratio(tmp, src, sr, &o)
|
||||
}
|
||||
|
||||
// TODO: honor o.DstMask.
|
||||
if o.DstMask != nil {
|
||||
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) {
|
||||
var o Options
|
||||
|
|
154
draw/impl.go
154
draw/impl.go
|
@ -527,6 +527,7 @@ func (nnInterpolator) scale_Image_Image_Over(dst Image, dr, adr image.Rectangle,
|
|||
dh2 := uint64(dr.Dy()) * 2
|
||||
sw := uint64(sr.Dx())
|
||||
sh := uint64(sr.Dy())
|
||||
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||
dstColorRGBA64 := &color.RGBA64{}
|
||||
dstColor := color.Color(dstColorRGBA64)
|
||||
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
|
||||
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()
|
||||
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
|
||||
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
|
||||
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
|
||||
sw := uint64(sr.Dx())
|
||||
sh := uint64(sr.Dy())
|
||||
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||
dstColorRGBA64 := &color.RGBA64{}
|
||||
dstColor := color.Color(dstColorRGBA64)
|
||||
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
||||
|
@ -557,6 +566,20 @@ func (nnInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle,
|
|||
for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
|
||||
sx := (2*uint64(dx) + 1) * sw / dw2
|
||||
pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA()
|
||||
if dstMask != nil {
|
||||
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
|
||||
_, _, _, 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 - 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)
|
||||
|
@ -565,6 +588,7 @@ func (nnInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle,
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (nnInterpolator) transform_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point, opts *Options) {
|
||||
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
||||
|
@ -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) {
|
||||
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||
dstColorRGBA64 := &color.RGBA64{}
|
||||
dstColor := color.Color(dstColorRGBA64)
|
||||
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()
|
||||
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
|
||||
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
|
||||
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) {
|
||||
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||
dstColorRGBA64 := &color.RGBA64{}
|
||||
dstColor := color.Color(dstColorRGBA64)
|
||||
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
||||
|
@ -940,6 +973,20 @@ func (nnInterpolator) transform_Image_Image_Src(dst Image, dr, adr image.Rectang
|
|||
continue
|
||||
}
|
||||
pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
|
||||
if dstMask != nil {
|
||||
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
|
||||
_, _, _, 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 - 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)
|
||||
|
@ -948,6 +995,7 @@ func (nnInterpolator) transform_Image_Image_Src(dst Image, dr, adr image.Rectang
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (z ablInterpolator) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
|
||||
var o Options
|
||||
|
@ -2470,6 +2518,7 @@ func (ablInterpolator) scale_Image_Image_Over(dst Image, dr, adr image.Rectangle
|
|||
yscale := float64(sh) / float64(dr.Dy())
|
||||
xscale := float64(sw) / float64(dr.Dx())
|
||||
swMinus1, shMinus1 := sw-1, sh-1
|
||||
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||
dstColorRGBA64 := &color.RGBA64{}
|
||||
dstColor := color.Color(dstColorRGBA64)
|
||||
|
||||
|
@ -2541,6 +2590,13 @@ func (ablInterpolator) scale_Image_Image_Over(dst Image, dr, adr image.Rectangle
|
|||
pb := uint32(s11b)
|
||||
pa := uint32(s11a)
|
||||
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
|
||||
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
|
||||
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())
|
||||
xscale := float64(sw) / float64(dr.Dx())
|
||||
swMinus1, shMinus1 := sw-1, sh-1
|
||||
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||
dstColorRGBA64 := &color.RGBA64{}
|
||||
dstColor := color.Color(dstColorRGBA64)
|
||||
|
||||
|
@ -2627,6 +2684,20 @@ func (ablInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle,
|
|||
pg := uint32(s11g)
|
||||
pb := uint32(s11b)
|
||||
pa := uint32(s11a)
|
||||
if dstMask != nil {
|
||||
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
|
||||
_, _, _, 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 - 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)
|
||||
|
@ -2635,6 +2706,7 @@ func (ablInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle,
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ablInterpolator) transform_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point, opts *Options) {
|
||||
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
||||
|
@ -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) {
|
||||
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||
dstColorRGBA64 := &color.RGBA64{}
|
||||
dstColor := color.Color(dstColorRGBA64)
|
||||
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)
|
||||
pa := uint32(s11a)
|
||||
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
|
||||
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
|
||||
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) {
|
||||
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||
dstColorRGBA64 := &color.RGBA64{}
|
||||
dstColor := color.Color(dstColorRGBA64)
|
||||
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
||||
|
@ -4141,6 +4222,20 @@ func (ablInterpolator) transform_Image_Image_Src(dst Image, dr, adr image.Rectan
|
|||
pg := uint32(s11g)
|
||||
pb := uint32(s11b)
|
||||
pa := uint32(s11a)
|
||||
if dstMask != nil {
|
||||
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
|
||||
_, _, _, 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 - 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)
|
||||
|
@ -4149,6 +4244,7 @@ func (ablInterpolator) transform_Image_Image_Src(dst Image, dr, adr image.Rectan
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
|
@ -4221,7 +4317,14 @@ func (z *kernelScaler) Scale(dst Image, dr image.Rectangle, src image.Image, sr
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: honor o.DstMask.
|
||||
if o.DstMask != nil {
|
||||
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 {
|
||||
switch o.Op {
|
||||
case Over:
|
||||
switch dst := dst.(type) {
|
||||
|
@ -4239,6 +4342,7 @@ func (z *kernelScaler) Scale(dst Image, dr image.Rectangle, src image.Image, sr
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (q *Kernel) Transform(dst Image, s2d *f64.Aff3, src image.Image, sr image.Rectangle, opts *Options) {
|
||||
var o Options
|
||||
|
@ -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) {
|
||||
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||
dstColorRGBA64 := &color.RGBA64{}
|
||||
dstColor := color.Color(dstColorRGBA64)
|
||||
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))
|
||||
pb0 := uint32(ftou(pb * 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
|
||||
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr0)
|
||||
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) {
|
||||
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||
dstColorRGBA64 := &color.RGBA64{}
|
||||
dstColor := color.Color(dstColorRGBA64)
|
||||
for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
|
||||
|
@ -4772,6 +4885,20 @@ func (z *kernelScaler) scaleY_Image_Src(dst Image, dr, adr image.Rectangle, tmp
|
|||
pb = pa
|
||||
}
|
||||
|
||||
if dstMask != nil {
|
||||
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
|
||||
_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
|
||||
pr := uint32(ftou(pr*s.invTotalWeight)) * ma / 0xffff
|
||||
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)
|
||||
|
@ -4780,6 +4907,7 @@ func (z *kernelScaler) scaleY_Image_Src(dst Image, dr, adr image.Rectangle, tmp
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (q *Kernel) transform_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
|
||||
// When shrinking, broaden the effective kernel support so that we still
|
||||
|
@ -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)))
|
||||
yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
|
||||
|
||||
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||
dstColorRGBA64 := &color.RGBA64{}
|
||||
dstColor := color.Color(dstColorRGBA64)
|
||||
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))
|
||||
pb0 := uint32(fffftou(pb))
|
||||
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
|
||||
dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr0)
|
||||
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)))
|
||||
yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
|
||||
|
||||
dstMask, dmp := opts.DstMask, opts.DstMaskP
|
||||
dstColorRGBA64 := &color.RGBA64{}
|
||||
dstColor := color.Color(dstColorRGBA64)
|
||||
for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
|
||||
|
@ -6296,6 +6433,20 @@ func (q *Kernel) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d
|
|||
pb = pa
|
||||
}
|
||||
|
||||
if dstMask != nil {
|
||||
qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
|
||||
_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
|
||||
pr := uint32(fffftou(pr)) * ma / 0xffff
|
||||
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)
|
||||
|
@ -6304,3 +6455,4 @@ func (q *Kernel) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,8 +24,12 @@ func Copy(dst Image, dp image.Point, src image.Image, sr image.Rectangle, opts *
|
|||
o = *opts
|
||||
}
|
||||
dr := sr.Add(dp.Sub(sr.Min))
|
||||
// TODO: honor o.DstMask and o.SrcMask.
|
||||
if o.DstMask == nil {
|
||||
// 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
|
||||
|
@ -89,7 +93,7 @@ type Options struct {
|
|||
DstMaskP image.Point
|
||||
SrcMask image.Image
|
||||
SrcMaskP image.Point
|
||||
// TODO: actually implement DstMask and SrcMask.
|
||||
// TODO: actually implement SrcMask.
|
||||
|
||||
// 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
|
||||
// type-specific fast path implementations.
|
||||
type (
|
||||
|
|
Loading…
Reference in New Issue
Block a user