vision/filter.go

80 lines
1.9 KiB
Go

package vision
import (
"image"
"image/color"
"math"
"github.com/disintegration/imaging"
"github.com/fogleman/gg"
)
// Sepia 应用怀旧滤镜
func (c *Canvas) Sepia() {
img := c.dc.Image()
bounds := img.Bounds()
w, h := bounds.Dx(), bounds.Dy()
result := image.NewRGBA(bounds)
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
r, g, b, a := img.At(x, y).RGBA()
r8, g8, b8 := float64(r>>8), float64(g>>8), float64(b>>8)
tr := 0.393*r8 + 0.769*g8 + 0.189*b8
tg := 0.349*r8 + 0.686*g8 + 0.168*b8
tb := 0.272*r8 + 0.534*g8 + 0.131*b8
if tr > 255 { tr = 255 }
if tg > 255 { tg = 255 }
if tb > 255 { tb = 255 }
result.SetRGBA(x, y, color.RGBA{uint8(tr), uint8(tg), uint8(tb), uint8(a >> 8)})
}
}
c.dc = gg.NewContextForImage(result)
}
// Pixelate 像素化处理
func (c *Canvas) Pixelate(size int) {
if size <= 1 { return }
img := c.dc.Image()
bounds := img.Bounds()
w, h := bounds.Dx(), bounds.Dy()
// 先缩小再放大实现像素化
small := imaging.Resize(img, w/size, h/size, imaging.NearestNeighbor)
pixelated := imaging.Resize(small, w, h, imaging.NearestNeighbor)
c.dc = gg.NewContextForImage(pixelated)
}
// Vignette 应用暗角效果
func (c *Canvas) Vignette(intensity float64) {
w, h := float64(c.Width()), float64(c.Height())
cx, cy := w/2, h/2
maxDist := math.Sqrt(cx*cx + cy*cy)
c.dc.Push()
for y := 0.0; y < h; y += 2 {
for x := 0.0; x < w; x += 2 {
dist := math.Sqrt((x-cx)*(x-cx) + (y-cy)*(y-cy))
factor := 1.0 - (dist/maxDist)*intensity
if factor < 0 { factor = 0 }
r, g, b, a := c.dc.Image().At(int(x), int(y)).RGBA()
c.dc.SetColor(color.RGBA{
R: uint8(float64(r>>8) * factor),
G: uint8(float64(g>>8) * factor),
B: uint8(float64(b>>8) * factor),
A: uint8(a >> 8),
})
c.dc.SetPixel(int(x), int(y))
c.dc.SetPixel(int(x+1), int(y))
c.dc.SetPixel(int(x), int(y+1))
c.dc.SetPixel(int(x+1), int(y+1))
}
}
c.dc.Pop()
}