90 lines
1.9 KiB
Go
90 lines
1.9 KiB
Go
package goeffects
|
|
|
|
// Package copied from https://github.com/markdaws/go-effects
|
|
|
|
import (
|
|
"image"
|
|
"math"
|
|
"runtime"
|
|
)
|
|
|
|
type sobel struct {
|
|
threshold int
|
|
invert bool
|
|
}
|
|
|
|
// NewSobel the input image should be a grayscale image, the output will be a version of
|
|
// the input image with the Sobel edge detector applied to it. A value of -1 for threshold
|
|
// will return an image whos rgb values are the sobel intensity values, if 0 <= threshold <= 255
|
|
// then the rgb values will be 255 if the intensity is >= threshold and 0 if the intensity
|
|
// is < threshold
|
|
func NewSobel(threshold int, invert bool) Effect {
|
|
return &sobel{
|
|
threshold: threshold,
|
|
invert: invert,
|
|
}
|
|
}
|
|
|
|
func (s *sobel) Apply(img *Image, numRoutines int) (*Image, error) {
|
|
if numRoutines == 0 {
|
|
numRoutines = runtime.GOMAXPROCS(0)
|
|
}
|
|
|
|
sobelX := [][]int{
|
|
{-1, 0, 1},
|
|
{-2, 0, 2},
|
|
{-1, 0, 1},
|
|
}
|
|
sobelY := [][]int{
|
|
{-1, -2, -1},
|
|
{0, 0, 0},
|
|
{1, 2, 1},
|
|
}
|
|
|
|
pf := func(ri, x, y, offset, inStride int, inPix, outPix []uint8) {
|
|
var px, py int
|
|
for dy := -1; dy <= 1; dy++ {
|
|
for dx := -1; dx <= 1; dx++ {
|
|
pOffset := offset + (dx*4 + dy*inStride)
|
|
r := int(inPix[pOffset])
|
|
px += sobelX[dx+1][dy+1] * r
|
|
py += sobelY[dx+1][dy+1] * r
|
|
}
|
|
}
|
|
|
|
val := uint8(math.Sqrt(float64(px*px + py*py)))
|
|
if s.threshold != -1 {
|
|
if val >= uint8(s.threshold) {
|
|
val = 255
|
|
} else {
|
|
val = 0
|
|
}
|
|
}
|
|
|
|
if s.invert {
|
|
val = 255 - val
|
|
}
|
|
outPix[offset] = val
|
|
outPix[offset+1] = val
|
|
outPix[offset+2] = val
|
|
outPix[offset+3] = 255
|
|
}
|
|
|
|
out := &Image{
|
|
img: image.NewRGBA(image.Rectangle{
|
|
Min: image.Point{X: 0, Y: 0},
|
|
Max: image.Point{X: img.Width, Y: img.Height},
|
|
}),
|
|
Width: img.Width,
|
|
Height: img.Height,
|
|
Bounds: Rect{
|
|
X: img.Bounds.X + 1,
|
|
Y: img.Bounds.Y + 1,
|
|
Width: img.Bounds.Width - 2,
|
|
Height: img.Bounds.Height - 2,
|
|
},
|
|
}
|
|
|
|
runParallel(numRoutines, img, out.Bounds, out, pf, 0)
|
|
return out, nil
|
|
}
|