80 lines
1.9 KiB
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()
|
|
}
|