From 2bada11da1307198a3be2ecb086aab6e78226ba6 Mon Sep 17 00:00:00 2001 From: David Ashby Date: Mon, 11 Jan 2021 19:47:29 -0500 Subject: [PATCH] add floyd-steinberg --- main.go | 2 ++ quantizer.go | 48 ++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/main.go b/main.go index 034c9f2..1f648dd 100644 --- a/main.go +++ b/main.go @@ -51,6 +51,8 @@ func main() { new = apply(i, bayerDithering(1, true)) case "simpleerror": new = apply(i, simpleErrorDiffusion()) + case "floydsteinberg": + new = apply(i, floydSteinberg()) default: fmt.Printf("unknown ditherer option: %s\n", ditherer) os.Exit(2) diff --git a/quantizer.go b/quantizer.go index 0c0340e..b7ceaa6 100644 --- a/quantizer.go +++ b/quantizer.go @@ -122,28 +122,60 @@ func bayerDithering(level int, invert bool) quantizerFunction { } } -func applyError(diffusionMatrix map[coord]float64, divisor float64, quantError float64, currentPixel coord, errMap map[coord]float64) { - for c, i := range diffusionMatrix { +type diffusion struct { + matrix map[coord]float64 + divisor float64 +} + +func applyError(diffusion diffusion, quantError float64, currentPixel coord, errMap map[coord]float64) { + for c, i := range diffusion.matrix { target := coord{x: currentPixel.x + c.x, y: currentPixel.y + c.y} - errMap[target] = errMap[target] + (quantError * (i / divisor)) + errMap[target] = errMap[target] + (quantError * (i / diffusion.divisor)) } } func simpleErrorDiffusion() quantizerFunction { errMap := make(map[coord]float64) - diffusionMatrix := map[coord]float64{ - {x: 1, y: 0}: 1.0, - {x: 0, y: 1}: 1.0, + d := diffusion{ + divisor: 2.0, + matrix: map[coord]float64{ + {x: 1, y: 0}: 1.0, + {x: 0, y: 1}: 1.0, + }, } return func(x int, y int, c color.Color) color.Color { p := coord{x: x, y: y} l := luminence(c) + errMap[p] delete(errMap, p) // don't let the error map grow too big if l > 0.5 { - applyError(diffusionMatrix, 2.0, l-1.0, p, errMap) + applyError(d, l-1.0, p, errMap) return color.White } - applyError(diffusionMatrix, 2.0, l, p, errMap) + applyError(d, l, p, errMap) + return color.Black + } +} + +func floydSteinberg() quantizerFunction { + errMap := make(map[coord]float64) + d := diffusion{ + divisor: 16.0, + matrix: map[coord]float64{ + {x: 1, y: 0}: 7.0, + {x: -1, y: 1}: 3.0, + {x: 0, y: 1}: 5.0, + {x: 1, y: 1}: 1.0, + }, + } + return func(x int, y int, c color.Color) color.Color { + p := coord{x: x, y: y} + l := luminence(c) + errMap[p] + delete(errMap, p) // don't let the error map grow too big + if l > 0.5 { + applyError(d, l-1.0, p, errMap) + return color.White + } + applyError(d, l, p, errMap) return color.Black } }