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
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) |
|
}
|
|
|