Files
opencloud/vendor/github.com/kovidgoyal/imaging/effects.go
dependabot[bot] 85361fca67 build(deps): bump github.com/kovidgoyal/imaging from 1.7.2 to 1.8.17
Bumps [github.com/kovidgoyal/imaging](https://github.com/kovidgoyal/imaging) from 1.7.2 to 1.8.17.
- [Release notes](https://github.com/kovidgoyal/imaging/releases)
- [Changelog](https://github.com/kovidgoyal/imaging/blob/master/.goreleaser.yaml)
- [Commits](https://github.com/kovidgoyal/imaging/compare/v1.7.2...v1.8.17)

---
updated-dependencies:
- dependency-name: github.com/kovidgoyal/imaging
  dependency-version: 1.8.17
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-26 14:46:30 +01:00

167 lines
3.9 KiB
Go

package imaging
import (
"image"
"math"
"github.com/kovidgoyal/imaging/nrgba"
)
func gaussianBlurKernel(x, sigma float64) float64 {
return math.Exp(-(x*x)/(2*sigma*sigma)) / (sigma * math.Sqrt(2*math.Pi))
}
// Blur produces a blurred version of the image using a Gaussian function.
// Sigma parameter must be positive and indicates how much the image will be blurred.
//
// Example:
//
// dstImage := imaging.Blur(srcImage, 3.5)
func Blur(img image.Image, sigma float64) *image.NRGBA {
if sigma <= 0 {
return Clone(img)
}
radius := int(math.Ceil(sigma * 3.0))
kernel := make([]float64, radius+1)
for i := 0; i <= radius; i++ {
kernel[i] = gaussianBlurKernel(float64(i), sigma)
}
return blurVertical(blurHorizontal(img, kernel), kernel)
}
func blurHorizontal(img image.Image, kernel []float64) *image.NRGBA {
w, h := img.Bounds().Dx(), img.Bounds().Dy()
src := nrgba.NewNRGBAScanner(img)
dst := image.NewNRGBA(image.Rect(0, 0, w, h))
radius := len(kernel) - 1
if err := run_in_parallel_over_range(0, func(start, limit int) {
scanLine := make([]uint8, w*4)
scanLineF := make([]float64, len(scanLine))
for y := start; y < limit; y++ {
src.Scan(0, y, w, y+1, scanLine)
for i, v := range scanLine {
scanLineF[i] = float64(v)
}
for x := range w {
minv := max(0, x-radius)
maxv := min(x+radius, w-1)
var r, g, b, a, wsum float64
for ix := minv; ix <= maxv; ix++ {
i := ix * 4
weight := kernel[absint(x-ix)]
wsum += weight
s := scanLineF[i : i+4 : i+4]
wa := s[3] * weight
r += s[0] * wa
g += s[1] * wa
b += s[2] * wa
a += wa
}
if a != 0 {
aInv := 1 / a
j := y*dst.Stride + x*4
d := dst.Pix[j : j+4 : j+4]
d[0] = clamp(r * aInv)
d[1] = clamp(g * aInv)
d[2] = clamp(b * aInv)
d[3] = clamp(a / wsum)
}
}
}
}, 0, h); err != nil {
panic(err)
}
return dst
}
func blurVertical(img image.Image, kernel []float64) *image.NRGBA {
w, h := img.Bounds().Dx(), img.Bounds().Dy()
src := nrgba.NewNRGBAScanner(img)
dst := image.NewNRGBA(image.Rect(0, 0, w, h))
radius := len(kernel) - 1
if err := run_in_parallel_over_range(0, func(start, limit int) {
scanLine := make([]uint8, h*4)
scanLineF := make([]float64, len(scanLine))
for x := start; x < limit; x++ {
src.Scan(x, 0, x+1, h, scanLine)
for i, v := range scanLine {
scanLineF[i] = float64(v)
}
for y := range h {
minv := max(0, y-radius)
maxv := min(y+radius, h-1)
var r, g, b, a, wsum float64
for iy := minv; iy <= maxv; iy++ {
i := iy * 4
weight := kernel[absint(y-iy)]
wsum += weight
s := scanLineF[i : i+4 : i+4]
wa := s[3] * weight
r += s[0] * wa
g += s[1] * wa
b += s[2] * wa
a += wa
}
if a != 0 {
aInv := 1 / a
j := y*dst.Stride + x*4
d := dst.Pix[j : j+4 : j+4]
d[0] = clamp(r * aInv)
d[1] = clamp(g * aInv)
d[2] = clamp(b * aInv)
d[3] = clamp(a / wsum)
}
}
}
}, 0, w); err != nil {
panic(err)
}
return dst
}
// Sharpen produces a sharpened version of the image.
// Sigma parameter must be positive and indicates how much the image will be sharpened.
//
// Example:
//
// dstImage := imaging.Sharpen(srcImage, 3.5)
func Sharpen(img image.Image, sigma float64) *image.NRGBA {
if sigma <= 0 {
return Clone(img)
}
w, h := img.Bounds().Dx(), img.Bounds().Dy()
src := nrgba.NewNRGBAScanner(img)
dst := image.NewNRGBA(image.Rect(0, 0, w, h))
blurred := Blur(img, sigma)
if err := run_in_parallel_over_range(0, func(start, limit int) {
scanLine := make([]uint8, w*4)
for y := start; y < limit; y++ {
src.Scan(0, y, w, y+1, scanLine)
j := y * dst.Stride
for i := 0; i < w*4; i++ {
val := int(scanLine[i])<<1 - int(blurred.Pix[j])
if val < 0 {
val = 0
} else if val > 0xff {
val = 0xff
}
dst.Pix[j] = uint8(val)
j++
}
}
}, 0, h); err != nil {
panic(err)
}
return dst
}