summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/disintegration/imaging/transform.go
diff options
context:
space:
mode:
authorWim <wim@42.be>2020-12-31 14:48:12 +0100
committerGitHub <noreply@github.com>2020-12-31 14:48:12 +0100
commit4f20ebead36876a88391bf033d1de3e4cf0228da (patch)
tree70b6fd79c6a5e00c958c29a7bd3926f074e76ba6 /vendor/github.com/disintegration/imaging/transform.go
parenta9f89dbc645aafc68daa9fc8d589f55104b535c7 (diff)
downloadmatterbridge-msglm-4f20ebead36876a88391bf033d1de3e4cf0228da.tar.gz
matterbridge-msglm-4f20ebead36876a88391bf033d1de3e4cf0228da.tar.bz2
matterbridge-msglm-4f20ebead36876a88391bf033d1de3e4cf0228da.zip
Update vendor for next release (#1343)
Diffstat (limited to 'vendor/github.com/disintegration/imaging/transform.go')
-rw-r--r--vendor/github.com/disintegration/imaging/transform.go268
1 files changed, 268 insertions, 0 deletions
diff --git a/vendor/github.com/disintegration/imaging/transform.go b/vendor/github.com/disintegration/imaging/transform.go
new file mode 100644
index 00000000..fe4a92f9
--- /dev/null
+++ b/vendor/github.com/disintegration/imaging/transform.go
@@ -0,0 +1,268 @@
+package imaging
+
+import (
+ "image"
+ "image/color"
+ "math"
+)
+
+// FlipH flips the image horizontally (from left to right) and returns the transformed image.
+func FlipH(img image.Image) *image.NRGBA {
+ src := newScanner(img)
+ dstW := src.w
+ dstH := src.h
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ parallel(0, dstH, func(ys <-chan int) {
+ for dstY := range ys {
+ i := dstY * dst.Stride
+ srcY := dstY
+ src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize])
+ reverse(dst.Pix[i : i+rowSize])
+ }
+ })
+ return dst
+}
+
+// FlipV flips the image vertically (from top to bottom) and returns the transformed image.
+func FlipV(img image.Image) *image.NRGBA {
+ src := newScanner(img)
+ dstW := src.w
+ dstH := src.h
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ parallel(0, dstH, func(ys <-chan int) {
+ for dstY := range ys {
+ i := dstY * dst.Stride
+ srcY := dstH - dstY - 1
+ src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize])
+ }
+ })
+ return dst
+}
+
+// Transpose flips the image horizontally and rotates 90 degrees counter-clockwise.
+func Transpose(img image.Image) *image.NRGBA {
+ src := newScanner(img)
+ dstW := src.h
+ dstH := src.w
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ parallel(0, dstH, func(ys <-chan int) {
+ for dstY := range ys {
+ i := dstY * dst.Stride
+ srcX := dstY
+ src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
+ }
+ })
+ return dst
+}
+
+// Transverse flips the image vertically and rotates 90 degrees counter-clockwise.
+func Transverse(img image.Image) *image.NRGBA {
+ src := newScanner(img)
+ dstW := src.h
+ dstH := src.w
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ parallel(0, dstH, func(ys <-chan int) {
+ for dstY := range ys {
+ i := dstY * dst.Stride
+ srcX := dstH - dstY - 1
+ src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
+ reverse(dst.Pix[i : i+rowSize])
+ }
+ })
+ return dst
+}
+
+// Rotate90 rotates the image 90 degrees counter-clockwise and returns the transformed image.
+func Rotate90(img image.Image) *image.NRGBA {
+ src := newScanner(img)
+ dstW := src.h
+ dstH := src.w
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ parallel(0, dstH, func(ys <-chan int) {
+ for dstY := range ys {
+ i := dstY * dst.Stride
+ srcX := dstH - dstY - 1
+ src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
+ }
+ })
+ return dst
+}
+
+// Rotate180 rotates the image 180 degrees counter-clockwise and returns the transformed image.
+func Rotate180(img image.Image) *image.NRGBA {
+ src := newScanner(img)
+ dstW := src.w
+ dstH := src.h
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ parallel(0, dstH, func(ys <-chan int) {
+ for dstY := range ys {
+ i := dstY * dst.Stride
+ srcY := dstH - dstY - 1
+ src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize])
+ reverse(dst.Pix[i : i+rowSize])
+ }
+ })
+ return dst
+}
+
+// Rotate270 rotates the image 270 degrees counter-clockwise and returns the transformed image.
+func Rotate270(img image.Image) *image.NRGBA {
+ src := newScanner(img)
+ dstW := src.h
+ dstH := src.w
+ rowSize := dstW * 4
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+ parallel(0, dstH, func(ys <-chan int) {
+ for dstY := range ys {
+ i := dstY * dst.Stride
+ srcX := dstY
+ src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize])
+ reverse(dst.Pix[i : i+rowSize])
+ }
+ })
+ return dst
+}
+
+// Rotate rotates an image by the given angle counter-clockwise .
+// The angle parameter is the rotation angle in degrees.
+// The bgColor parameter specifies the color of the uncovered zone after the rotation.
+func Rotate(img image.Image, angle float64, bgColor color.Color) *image.NRGBA {
+ angle = angle - math.Floor(angle/360)*360
+
+ switch angle {
+ case 0:
+ return Clone(img)
+ case 90:
+ return Rotate90(img)
+ case 180:
+ return Rotate180(img)
+ case 270:
+ return Rotate270(img)
+ }
+
+ src := toNRGBA(img)
+ srcW := src.Bounds().Max.X
+ srcH := src.Bounds().Max.Y
+ dstW, dstH := rotatedSize(srcW, srcH, angle)
+ dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
+
+ if dstW <= 0 || dstH <= 0 {
+ return dst
+ }
+
+ srcXOff := float64(srcW)/2 - 0.5
+ srcYOff := float64(srcH)/2 - 0.5
+ dstXOff := float64(dstW)/2 - 0.5
+ dstYOff := float64(dstH)/2 - 0.5
+
+ bgColorNRGBA := color.NRGBAModel.Convert(bgColor).(color.NRGBA)
+ sin, cos := math.Sincos(math.Pi * angle / 180)
+
+ parallel(0, dstH, func(ys <-chan int) {
+ for dstY := range ys {
+ for dstX := 0; dstX < dstW; dstX++ {
+ xf, yf := rotatePoint(float64(dstX)-dstXOff, float64(dstY)-dstYOff, sin, cos)
+ xf, yf = xf+srcXOff, yf+srcYOff
+ interpolatePoint(dst, dstX, dstY, src, xf, yf, bgColorNRGBA)
+ }
+ }
+ })
+
+ return dst
+}
+
+func rotatePoint(x, y, sin, cos float64) (float64, float64) {
+ return x*cos - y*sin, x*sin + y*cos
+}
+
+func rotatedSize(w, h int, angle float64) (int, int) {
+ if w <= 0 || h <= 0 {
+ return 0, 0
+ }
+
+ sin, cos := math.Sincos(math.Pi * angle / 180)
+ x1, y1 := rotatePoint(float64(w-1), 0, sin, cos)
+ x2, y2 := rotatePoint(float64(w-1), float64(h-1), sin, cos)
+ x3, y3 := rotatePoint(0, float64(h-1), sin, cos)
+
+ minx := math.Min(x1, math.Min(x2, math.Min(x3, 0)))
+ maxx := math.Max(x1, math.Max(x2, math.Max(x3, 0)))
+ miny := math.Min(y1, math.Min(y2, math.Min(y3, 0)))
+ maxy := math.Max(y1, math.Max(y2, math.Max(y3, 0)))
+
+ neww := maxx - minx + 1
+ if neww-math.Floor(neww) > 0.1 {
+ neww++
+ }
+ newh := maxy - miny + 1
+ if newh-math.Floor(newh) > 0.1 {
+ newh++
+ }
+
+ return int(neww), int(newh)
+}
+
+func interpolatePoint(dst *image.NRGBA, dstX, dstY int, src *image.NRGBA, xf, yf float64, bgColor color.NRGBA) {
+ j := dstY*dst.Stride + dstX*4
+ d := dst.Pix[j : j+4 : j+4]
+
+ x0 := int(math.Floor(xf))
+ y0 := int(math.Floor(yf))
+ bounds := src.Bounds()
+ if !image.Pt(x0, y0).In(image.Rect(bounds.Min.X-1, bounds.Min.Y-1, bounds.Max.X, bounds.Max.Y)) {
+ d[0] = bgColor.R
+ d[1] = bgColor.G
+ d[2] = bgColor.B
+ d[3] = bgColor.A
+ return
+ }
+
+ xq := xf - float64(x0)
+ yq := yf - float64(y0)
+ points := [4]image.Point{
+ {x0, y0},
+ {x0 + 1, y0},
+ {x0, y0 + 1},
+ {x0 + 1, y0 + 1},
+ }
+ weights := [4]float64{
+ (1 - xq) * (1 - yq),
+ xq * (1 - yq),
+ (1 - xq) * yq,
+ xq * yq,
+ }
+
+ var r, g, b, a float64
+ for i := 0; i < 4; i++ {
+ p := points[i]
+ w := weights[i]
+ if p.In(bounds) {
+ i := p.Y*src.Stride + p.X*4
+ s := src.Pix[i : i+4 : i+4]
+ wa := float64(s[3]) * w
+ r += float64(s[0]) * wa
+ g += float64(s[1]) * wa
+ b += float64(s[2]) * wa
+ a += wa
+ } else {
+ wa := float64(bgColor.A) * w
+ r += float64(bgColor.R) * wa
+ g += float64(bgColor.G) * wa
+ b += float64(bgColor.B) * wa
+ a += wa
+ }
+ }
+ if a != 0 {
+ aInv := 1 / a
+ d[0] = clamp(r * aInv)
+ d[1] = clamp(g * aInv)
+ d[2] = clamp(b * aInv)
+ d[3] = clamp(a)
+ }
+}