Fix Avatar Resize (resize algo NearestNeighbor -> Bilinear) (#12745) (#12750)

* Update Vendor github.com/nfnt/resize

* switch resize algo NearestNeighbor -> Bilinear
pull/12751/head^2
6543 4 years ago committed by GitHub
parent 2806a312e1
commit 0bb56a413d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      go.mod
  2. 4
      go.sum
  3. 2
      modules/avatar/avatar.go
  4. 8
      vendor/github.com/nfnt/resize/.travis.yml
  5. 2
      vendor/github.com/nfnt/resize/README.md
  6. 6
      vendor/github.com/nfnt/resize/resize.go
  7. 390
      vendor/github.com/nfnt/resize/ycc.go
  8. 2
      vendor/modules.txt

@ -75,7 +75,7 @@ require (
github.com/microcosm-cc/bluemonday v1.0.3-0.20191119130333-0a75d7616912 github.com/microcosm-cc/bluemonday v1.0.3-0.20191119130333-0a75d7616912
github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-homedir v1.1.0
github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/niklasfasching/go-org v0.1.9 github.com/niklasfasching/go-org v0.1.9
github.com/oliamb/cutter v0.2.2 github.com/oliamb/cutter v0.2.2
github.com/olivere/elastic/v7 v7.0.9 github.com/olivere/elastic/v7 v7.0.9

@ -483,8 +483,8 @@ github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOl
github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc h1:z1PgdCCmYYVL0BoJTUgmAq1p7ca8fzYIPsNyfsN3xAU= github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc h1:z1PgdCCmYYVL0BoJTUgmAq1p7ca8fzYIPsNyfsN3xAU=
github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc/go.mod h1:np1wUFZ6tyoke22qDJZY40URn9Ae51gX7ljIWXN5TJs= github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc/go.mod h1:np1wUFZ6tyoke22qDJZY40URn9Ae51gX7ljIWXN5TJs=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 h1:BvoENQQU+fZ9uukda/RzCAL/191HHwJA5b13R6diVlY= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/niklasfasching/go-org v0.1.9 h1:Toz8WMIt+qJb52uYEk1YD/muLuOOmRt1CfkV+bKVMkI= github.com/niklasfasching/go-org v0.1.9 h1:Toz8WMIt+qJb52uYEk1YD/muLuOOmRt1CfkV+bKVMkI=

@ -89,6 +89,6 @@ func Prepare(data []byte) (*image.Image, error) {
} }
} }
img = resize.Resize(AvatarSize, AvatarSize, img, resize.NearestNeighbor) img = resize.Resize(AvatarSize, AvatarSize, img, resize.Bilinear)
return &img, nil return &img, nil
} }

@ -1,7 +1,7 @@
language: go language: go
go: go:
- 1.1 - "1.x"
- 1.2 - "1.1"
- 1.3 - "1.4"
- tip - "1.10"

@ -1,3 +1,5 @@
# This package is no longer being updated! Please look for alternatives if that bothers you.
Resize Resize
====== ======

@ -78,6 +78,7 @@ var blur = 1.0
// If one of the parameters width or height is set to 0, its size will be calculated so that // If one of the parameters width or height is set to 0, its size will be calculated so that
// the aspect ratio is that of the originating image. // the aspect ratio is that of the originating image.
// The resizing algorithm uses channels for parallel computation. // The resizing algorithm uses channels for parallel computation.
// If the input image has width or height of 0, it is returned unchanged.
func Resize(width, height uint, img image.Image, interp InterpolationFunction) image.Image { func Resize(width, height uint, img image.Image, interp InterpolationFunction) image.Image {
scaleX, scaleY := calcFactors(width, height, float64(img.Bounds().Dx()), float64(img.Bounds().Dy())) scaleX, scaleY := calcFactors(width, height, float64(img.Bounds().Dx()), float64(img.Bounds().Dy()))
if width == 0 { if width == 0 {
@ -92,6 +93,11 @@ func Resize(width, height uint, img image.Image, interp InterpolationFunction) i
return img return img
} }
// Input image has no pixels
if img.Bounds().Dx() <= 0 || img.Bounds().Dy() <= 0 {
return img
}
if interp == NearestNeighbor { if interp == NearestNeighbor {
return resizeNearest(width, height, scaleX, scaleY, img, interp) return resizeNearest(width, height, scaleX, scaleY, img, interp)
} }

@ -88,140 +88,300 @@ func newYCC(r image.Rectangle, s image.YCbCrSubsampleRatio) *ycc {
return &ycc{Pix: buf, Stride: 3 * w, Rect: r, SubsampleRatio: s} return &ycc{Pix: buf, Stride: 3 * w, Rect: r, SubsampleRatio: s}
} }
// Copy of image.YCbCrSubsampleRatio constants - this allows us to support
// older versions of Go where these constants are not defined (i.e. Go 1.4)
const (
ycbcrSubsampleRatio444 image.YCbCrSubsampleRatio = iota
ycbcrSubsampleRatio422
ycbcrSubsampleRatio420
ycbcrSubsampleRatio440
ycbcrSubsampleRatio411
ycbcrSubsampleRatio410
)
// YCbCr converts ycc to a YCbCr image with the same subsample ratio // YCbCr converts ycc to a YCbCr image with the same subsample ratio
// as the YCbCr image that ycc was generated from. // as the YCbCr image that ycc was generated from.
func (p *ycc) YCbCr() *image.YCbCr { func (p *ycc) YCbCr() *image.YCbCr {
ycbcr := image.NewYCbCr(p.Rect, p.SubsampleRatio) ycbcr := image.NewYCbCr(p.Rect, p.SubsampleRatio)
switch ycbcr.SubsampleRatio {
case ycbcrSubsampleRatio422:
return p.ycbcr422(ycbcr)
case ycbcrSubsampleRatio420:
return p.ycbcr420(ycbcr)
case ycbcrSubsampleRatio440:
return p.ycbcr440(ycbcr)
case ycbcrSubsampleRatio444:
return p.ycbcr444(ycbcr)
case ycbcrSubsampleRatio411:
return p.ycbcr411(ycbcr)
case ycbcrSubsampleRatio410:
return p.ycbcr410(ycbcr)
}
return ycbcr
}
// imageYCbCrToYCC converts a YCbCr image to a ycc image for resizing.
func imageYCbCrToYCC(in *image.YCbCr) *ycc {
w, h := in.Rect.Dx(), in.Rect.Dy()
p := ycc{
Pix: make([]uint8, 3*w*h),
Stride: 3 * w,
Rect: image.Rect(0, 0, w, h),
SubsampleRatio: in.SubsampleRatio,
}
switch in.SubsampleRatio {
case ycbcrSubsampleRatio422:
return convertToYCC422(in, &p)
case ycbcrSubsampleRatio420:
return convertToYCC420(in, &p)
case ycbcrSubsampleRatio440:
return convertToYCC440(in, &p)
case ycbcrSubsampleRatio444:
return convertToYCC444(in, &p)
case ycbcrSubsampleRatio411:
return convertToYCC411(in, &p)
case ycbcrSubsampleRatio410:
return convertToYCC410(in, &p)
}
return &p
}
func (p *ycc) ycbcr422(ycbcr *image.YCbCr) *image.YCbCr {
var off int var off int
Pix := p.Pix
Y := ycbcr.Y
Cb := ycbcr.Cb
Cr := ycbcr.Cr
for y := 0; y < ycbcr.Rect.Max.Y-ycbcr.Rect.Min.Y; y++ {
yy := y * ycbcr.YStride
cy := y * ycbcr.CStride
for x := 0; x < ycbcr.Rect.Max.X-ycbcr.Rect.Min.X; x++ {
ci := cy + x/2
Y[yy+x] = Pix[off+0]
Cb[ci] = Pix[off+1]
Cr[ci] = Pix[off+2]
off += 3
}
}
return ycbcr
}
switch ycbcr.SubsampleRatio { func (p *ycc) ycbcr420(ycbcr *image.YCbCr) *image.YCbCr {
case image.YCbCrSubsampleRatio422: var off int
for y := ycbcr.Rect.Min.Y; y < ycbcr.Rect.Max.Y; y++ { Pix := p.Pix
yy := (y - ycbcr.Rect.Min.Y) * ycbcr.YStride Y := ycbcr.Y
cy := (y - ycbcr.Rect.Min.Y) * ycbcr.CStride Cb := ycbcr.Cb
for x := ycbcr.Rect.Min.X; x < ycbcr.Rect.Max.X; x++ { Cr := ycbcr.Cr
xx := (x - ycbcr.Rect.Min.X) for y := 0; y < ycbcr.Rect.Max.Y-ycbcr.Rect.Min.Y; y++ {
yi := yy + xx yy := y * ycbcr.YStride
ci := cy + xx/2 cy := (y / 2) * ycbcr.CStride
ycbcr.Y[yi] = p.Pix[off+0] for x := 0; x < ycbcr.Rect.Max.X-ycbcr.Rect.Min.X; x++ {
ycbcr.Cb[ci] = p.Pix[off+1] ci := cy + x/2
ycbcr.Cr[ci] = p.Pix[off+2] Y[yy+x] = Pix[off+0]
off += 3 Cb[ci] = Pix[off+1]
} Cr[ci] = Pix[off+2]
off += 3
} }
case image.YCbCrSubsampleRatio420: }
for y := ycbcr.Rect.Min.Y; y < ycbcr.Rect.Max.Y; y++ { return ycbcr
yy := (y - ycbcr.Rect.Min.Y) * ycbcr.YStride }
cy := (y/2 - ycbcr.Rect.Min.Y/2) * ycbcr.CStride
for x := ycbcr.Rect.Min.X; x < ycbcr.Rect.Max.X; x++ { func (p *ycc) ycbcr440(ycbcr *image.YCbCr) *image.YCbCr {
xx := (x - ycbcr.Rect.Min.X) var off int
yi := yy + xx Pix := p.Pix
ci := cy + xx/2 Y := ycbcr.Y
ycbcr.Y[yi] = p.Pix[off+0] Cb := ycbcr.Cb
ycbcr.Cb[ci] = p.Pix[off+1] Cr := ycbcr.Cr
ycbcr.Cr[ci] = p.Pix[off+2] for y := 0; y < ycbcr.Rect.Max.Y-ycbcr.Rect.Min.Y; y++ {
off += 3 yy := y * ycbcr.YStride
} cy := (y / 2) * ycbcr.CStride
for x := 0; x < ycbcr.Rect.Max.X-ycbcr.Rect.Min.X; x++ {
ci := cy + x
Y[yy+x] = Pix[off+0]
Cb[ci] = Pix[off+1]
Cr[ci] = Pix[off+2]
off += 3
} }
case image.YCbCrSubsampleRatio440: }
for y := ycbcr.Rect.Min.Y; y < ycbcr.Rect.Max.Y; y++ { return ycbcr
yy := (y - ycbcr.Rect.Min.Y) * ycbcr.YStride }
cy := (y/2 - ycbcr.Rect.Min.Y/2) * ycbcr.CStride
for x := ycbcr.Rect.Min.X; x < ycbcr.Rect.Max.X; x++ { func (p *ycc) ycbcr444(ycbcr *image.YCbCr) *image.YCbCr {
xx := (x - ycbcr.Rect.Min.X) var off int
yi := yy + xx Pix := p.Pix
ci := cy + xx Y := ycbcr.Y
ycbcr.Y[yi] = p.Pix[off+0] Cb := ycbcr.Cb
ycbcr.Cb[ci] = p.Pix[off+1] Cr := ycbcr.Cr
ycbcr.Cr[ci] = p.Pix[off+2] for y := 0; y < ycbcr.Rect.Max.Y-ycbcr.Rect.Min.Y; y++ {
off += 3 yy := y * ycbcr.YStride
} cy := y * ycbcr.CStride
for x := 0; x < ycbcr.Rect.Max.X-ycbcr.Rect.Min.X; x++ {
ci := cy + x
Y[yy+x] = Pix[off+0]
Cb[ci] = Pix[off+1]
Cr[ci] = Pix[off+2]
off += 3
}
}
return ycbcr
}
func (p *ycc) ycbcr411(ycbcr *image.YCbCr) *image.YCbCr {
var off int
Pix := p.Pix
Y := ycbcr.Y
Cb := ycbcr.Cb
Cr := ycbcr.Cr
for y := 0; y < ycbcr.Rect.Max.Y-ycbcr.Rect.Min.Y; y++ {
yy := y * ycbcr.YStride
cy := y * ycbcr.CStride
for x := 0; x < ycbcr.Rect.Max.X-ycbcr.Rect.Min.X; x++ {
ci := cy + x/4
Y[yy+x] = Pix[off+0]
Cb[ci] = Pix[off+1]
Cr[ci] = Pix[off+2]
off += 3
} }
default: }
// Default to 4:4:4 subsampling. return ycbcr
for y := ycbcr.Rect.Min.Y; y < ycbcr.Rect.Max.Y; y++ { }
yy := (y - ycbcr.Rect.Min.Y) * ycbcr.YStride
cy := (y - ycbcr.Rect.Min.Y) * ycbcr.CStride func (p *ycc) ycbcr410(ycbcr *image.YCbCr) *image.YCbCr {
for x := ycbcr.Rect.Min.X; x < ycbcr.Rect.Max.X; x++ { var off int
xx := (x - ycbcr.Rect.Min.X) Pix := p.Pix
yi := yy + xx Y := ycbcr.Y
ci := cy + xx Cb := ycbcr.Cb
ycbcr.Y[yi] = p.Pix[off+0] Cr := ycbcr.Cr
ycbcr.Cb[ci] = p.Pix[off+1] for y := 0; y < ycbcr.Rect.Max.Y-ycbcr.Rect.Min.Y; y++ {
ycbcr.Cr[ci] = p.Pix[off+2] yy := y * ycbcr.YStride
off += 3 cy := (y / 2) * ycbcr.CStride
} for x := 0; x < ycbcr.Rect.Max.X-ycbcr.Rect.Min.X; x++ {
ci := cy + x/4
Y[yy+x] = Pix[off+0]
Cb[ci] = Pix[off+1]
Cr[ci] = Pix[off+2]
off += 3
} }
} }
return ycbcr return ycbcr
} }
// imageYCbCrToYCC converts a YCbCr image to a ycc image for resizing. func convertToYCC422(in *image.YCbCr, p *ycc) *ycc {
func imageYCbCrToYCC(in *image.YCbCr) *ycc {
w, h := in.Rect.Dx(), in.Rect.Dy()
r := image.Rect(0, 0, w, h)
buf := make([]uint8, 3*w*h)
p := ycc{Pix: buf, Stride: 3 * w, Rect: r, SubsampleRatio: in.SubsampleRatio}
var off int var off int
Pix := p.Pix
Y := in.Y
Cb := in.Cb
Cr := in.Cr
for y := 0; y < in.Rect.Max.Y-in.Rect.Min.Y; y++ {
yy := y * in.YStride
cy := y * in.CStride
for x := 0; x < in.Rect.Max.X-in.Rect.Min.X; x++ {
ci := cy + x/2
Pix[off+0] = Y[yy+x]
Pix[off+1] = Cb[ci]
Pix[off+2] = Cr[ci]
off += 3
}
}
return p
}
switch in.SubsampleRatio { func convertToYCC420(in *image.YCbCr, p *ycc) *ycc {
case image.YCbCrSubsampleRatio422: var off int
for y := in.Rect.Min.Y; y < in.Rect.Max.Y; y++ { Pix := p.Pix
yy := (y - in.Rect.Min.Y) * in.YStride Y := in.Y
cy := (y - in.Rect.Min.Y) * in.CStride Cb := in.Cb
for x := in.Rect.Min.X; x < in.Rect.Max.X; x++ { Cr := in.Cr
xx := (x - in.Rect.Min.X) for y := 0; y < in.Rect.Max.Y-in.Rect.Min.Y; y++ {
yi := yy + xx yy := y * in.YStride
ci := cy + xx/2 cy := (y / 2) * in.CStride
p.Pix[off+0] = in.Y[yi] for x := 0; x < in.Rect.Max.X-in.Rect.Min.X; x++ {
p.Pix[off+1] = in.Cb[ci] ci := cy + x/2
p.Pix[off+2] = in.Cr[ci] Pix[off+0] = Y[yy+x]
off += 3 Pix[off+1] = Cb[ci]
} Pix[off+2] = Cr[ci]
off += 3
} }
case image.YCbCrSubsampleRatio420: }
for y := in.Rect.Min.Y; y < in.Rect.Max.Y; y++ { return p
yy := (y - in.Rect.Min.Y) * in.YStride }
cy := (y/2 - in.Rect.Min.Y/2) * in.CStride
for x := in.Rect.Min.X; x < in.Rect.Max.X; x++ { func convertToYCC440(in *image.YCbCr, p *ycc) *ycc {
xx := (x - in.Rect.Min.X) var off int
yi := yy + xx Pix := p.Pix
ci := cy + xx/2 Y := in.Y
p.Pix[off+0] = in.Y[yi] Cb := in.Cb
p.Pix[off+1] = in.Cb[ci] Cr := in.Cr
p.Pix[off+2] = in.Cr[ci] for y := 0; y < in.Rect.Max.Y-in.Rect.Min.Y; y++ {
off += 3 yy := y * in.YStride
} cy := (y / 2) * in.CStride
for x := 0; x < in.Rect.Max.X-in.Rect.Min.X; x++ {
ci := cy + x
Pix[off+0] = Y[yy+x]
Pix[off+1] = Cb[ci]
Pix[off+2] = Cr[ci]
off += 3
} }
case image.YCbCrSubsampleRatio440: }
for y := in.Rect.Min.Y; y < in.Rect.Max.Y; y++ { return p
yy := (y - in.Rect.Min.Y) * in.YStride }
cy := (y/2 - in.Rect.Min.Y/2) * in.CStride
for x := in.Rect.Min.X; x < in.Rect.Max.X; x++ { func convertToYCC444(in *image.YCbCr, p *ycc) *ycc {
xx := (x - in.Rect.Min.X) var off int
yi := yy + xx Pix := p.Pix
ci := cy + xx Y := in.Y
p.Pix[off+0] = in.Y[yi] Cb := in.Cb
p.Pix[off+1] = in.Cb[ci] Cr := in.Cr
p.Pix[off+2] = in.Cr[ci] for y := 0; y < in.Rect.Max.Y-in.Rect.Min.Y; y++ {
off += 3 yy := y * in.YStride
} cy := y * in.CStride
for x := 0; x < in.Rect.Max.X-in.Rect.Min.X; x++ {
ci := cy + x
Pix[off+0] = Y[yy+x]
Pix[off+1] = Cb[ci]
Pix[off+2] = Cr[ci]
off += 3
} }
default: }
// Default to 4:4:4 subsampling. return p
for y := in.Rect.Min.Y; y < in.Rect.Max.Y; y++ { }
yy := (y - in.Rect.Min.Y) * in.YStride
cy := (y - in.Rect.Min.Y) * in.CStride func convertToYCC411(in *image.YCbCr, p *ycc) *ycc {
for x := in.Rect.Min.X; x < in.Rect.Max.X; x++ { var off int
xx := (x - in.Rect.Min.X) Pix := p.Pix
yi := yy + xx Y := in.Y
ci := cy + xx Cb := in.Cb
p.Pix[off+0] = in.Y[yi] Cr := in.Cr
p.Pix[off+1] = in.Cb[ci] for y := 0; y < in.Rect.Max.Y-in.Rect.Min.Y; y++ {
p.Pix[off+2] = in.Cr[ci] yy := y * in.YStride
off += 3 cy := y * in.CStride
} for x := 0; x < in.Rect.Max.X-in.Rect.Min.X; x++ {
ci := cy + x/4
Pix[off+0] = Y[yy+x]
Pix[off+1] = Cb[ci]
Pix[off+2] = Cr[ci]
off += 3
} }
} }
return &p return p
}
func convertToYCC410(in *image.YCbCr, p *ycc) *ycc {
var off int
Pix := p.Pix
Y := in.Y
Cb := in.Cb
Cr := in.Cr
for y := 0; y < in.Rect.Max.Y-in.Rect.Min.Y; y++ {
yy := y * in.YStride
cy := (y / 2) * in.CStride
for x := 0; x < in.Rect.Max.X-in.Rect.Min.X; x++ {
ci := cy + x/4
Pix[off+0] = Y[yy+x]
Pix[off+1] = Cb[ci]
Pix[off+2] = Cr[ci]
off += 3
}
}
return p
} }

@ -518,7 +518,7 @@ github.com/mschoch/smat
# github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc # github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc
## explicit ## explicit
github.com/msteinert/pam github.com/msteinert/pam
# github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 # github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
## explicit ## explicit
github.com/nfnt/resize github.com/nfnt/resize
# github.com/niklasfasching/go-org v0.1.9 # github.com/niklasfasching/go-org v0.1.9

Loading…
Cancel
Save