You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

92 lines
2.3 KiB

package main
// imports
import (
"github.com/fogleman/gg"
"image"
"image/color"
"math/rand"
)
// imports
type UserParams struct {
StrokeRatio float64
DestWidth int
DestHeight int
InitialAlpha float64
StrokeReduction float64
AlphaIncrease float64
StrokeInversionThreshold float64
StrokeJitter int
MinEdgeCount int
MaxEdgeCount int
}
type Sketch struct {
UserParams // embed for easier access
source image.Image
dc *gg.Context
sourceWidth int
sourceHeight int
strokeSize float64
initialStrokeSize float64
}
func NewSketch(source image.Image, userParams UserParams) *Sketch {
s := &Sketch{UserParams: userParams}
bounds := source.Bounds()
s.sourceWidth, s.sourceHeight = bounds.Max.X, bounds.Max.Y
s.initialStrokeSize = s.StrokeRatio * float64(s.DestWidth)
s.strokeSize = s.initialStrokeSize
canvas := gg.NewContext(s.DestWidth, s.DestHeight)
canvas.SetColor(color.Black)
canvas.DrawRectangle(0, 0, float64(s.DestWidth), float64(s.DestHeight))
canvas.FillPreserve()
s.source = source
s.dc = canvas
return s
}
func (s *Sketch) Update() {
rndX := rand.Float64() * float64(s.sourceWidth)
rndY := rand.Float64() * float64(s.sourceHeight)
r, g, b := rgb255(s.source.At(int(rndX), int(rndY)))
destX := rndX * float64(s.DestWidth) / float64(s.sourceWidth)
destX += float64(randRange(s.StrokeJitter))
destY := rndY * float64(s.DestHeight) / float64(s.sourceHeight)
destY += float64(randRange(s.StrokeJitter))
edges := s.MinEdgeCount + rand.Intn(s.MaxEdgeCount-s.MinEdgeCount+1)
s.dc.SetRGBA255(r, g, b, int(s.InitialAlpha))
s.dc.DrawRegularPolygon(edges, destX, destY, s.strokeSize, rand.Float64())
s.dc.FillPreserve()
if s.strokeSize <= s.StrokeInversionThreshold*s.initialStrokeSize {
if (r+g+b)/3 < 128 {
s.dc.SetRGBA255(255, 255, 255, int(s.InitialAlpha*2))
} else {
s.dc.SetRGBA255(0, 0, 0, int(s.InitialAlpha*2))
}
}
s.dc.Stroke()
s.strokeSize -= s.StrokeReduction * s.strokeSize
s.InitialAlpha += s.AlphaIncrease
}
func (s *Sketch) Output() image.Image {
return s.dc.Image()
}
func rgb255(c color.Color) (r, g, b int) {
r0, g0, b0, _ := c.RGBA()
return int(r0 / 257), int(g0 / 257), int(b0 / 257)
}
func randRange(max int) int {
return -max + rand.Intn(2*max)
}