-
-
Notifications
You must be signed in to change notification settings - Fork 10
/
dither_mono.go
60 lines (53 loc) · 1.38 KB
/
dither_mono.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package dither
import (
"image"
"image/color"
)
func (dither Dither) Monochrome(input image.Image, errorMultiplier float32) image.Image {
bounds := input.Bounds()
img := image.NewGray(bounds)
for x := bounds.Min.X; x < bounds.Dx(); x++ {
for y := bounds.Min.Y; y < bounds.Dy(); y++ {
pixel := input.At(x, y)
img.Set(x, y, pixel)
}
}
dx, dy := img.Bounds().Dx(), img.Bounds().Dy()
// Prepopulate multidimensional slice
errors := make([][]float32, dx)
for x := 0; x < dx; x++ {
errors[x] = make([]float32, dy)
for y := 0; y < dy; y++ {
errors[x][y] = 0
}
}
for x := 0; x < dx; x++ {
for y := 0; y < dy; y++ {
pix := float32(img.GrayAt(x, y).Y)
pix -= errors[x][y] * errorMultiplier
var quantError float32
// Diffuse the error of each calculation to the neighboring pixels
if pix < 128 {
quantError = -pix
pix = 0
} else {
quantError = 255 - pix
pix = 255
}
img.SetGray(x, y, color.Gray{Y: uint8(pix)})
// Diffuse error in two dimension
ydim := len(dither.Filter) - 1
xdim := len(dither.Filter[0]) / 2
for xx := 0; xx < ydim+1; xx++ {
for yy := -xdim; yy <= xdim-1; yy++ {
if y+yy < 0 || dy <= y+yy || x+xx < 0 || dx <= x+xx {
continue
}
// Adds the error of the previous pixel to the current pixel
errors[x+xx][y+yy] += quantError * dither.Filter[xx][yy+ydim]
}
}
}
}
return img
}