-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathbraille.go
74 lines (68 loc) · 2.54 KB
/
braille.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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package dotmatrix
import (
"image"
"image/color"
"io"
)
// Braille epresents an 8 dot braille pattern in x,y coordinates space. Eg:
// +----------+
// |(0,0)(1,0)|
// |(0,1)(1,1)|
// |(0,2)(1,2)|
// |(0,3)(1,3)|
// +----------+
type Braille [2][4]int
// Rune maps each point in braille to a dot identifier and
// calculates the corresponding unicode symbol.
// +------+
// |(1)(4)|
// |(2)(5)|
// |(3)(6)|
// |(7)(8)|
// +------+
// See https://en.wikipedia.org/wiki/Braille_Patterns#Identifying.2C_naming_and_ordering)
func (b Braille) Rune() rune {
lowEndian := [8]int{b[0][0], b[0][1], b[0][2], b[1][0], b[1][1], b[1][2], b[0][3], b[1][3]}
var v int
for i, x := range lowEndian {
v += int(x) << uint(i)
}
return rune(v) + '\u2800'
}
// String returns a unicode braille character. One of:
// ⣿ ⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯⠰⠱⠲⠳⠴⠵⠶⠷⠸⠹⠺⠻⠼⠽⠾⠿⡀⡁⡂⡃⡄⡅⡆⡇⡈⡉⡊⡋⡌⡍⡎⡏⡐⡑⡒⡓⡔⡕⡖⡗⡘⡙⡚⡛⡜⡝⡞⡟⡠⡡⡢⡣⡤⡥⡦⡧⡨⡩⡪⡫⡬⡭⡮⡯⡰⡱⡲⡳⡴⡵⡶⡷⡸⡹⡺⡻⡼⡽⡾⡿⢀⢁⢂⢃⢄⢅⢆⢇⢈⢉⢊⢋⢌⢍⢎⢏⢐⢑⢒⢓⢔⢕⢖⢗⢘⢙⢚⢛⢜⢝⢞⢟⢠⢡⢢⢣⢤⢥⢦⢧⢨⢩⢪⢫⢬⢭⢮⢯⢰⢱⢲⢳⢴⢵⢶⢷⢸⢹⢺⢻⢼⢽⢾⢿⣀⣁⣂⣃⣄⣅⣆⣇⣈⣉⣊⣋⣌⣍⣎⣏⣐⣑⣒⣓⣔⣕⣖⣗⣘⣙⣚⣛⣜⣝⣞⣟⣠⣡⣢⣣⣤⣥⣦⣧⣨⣩⣪⣫⣬⣭⣮⣯⣰⣱⣲⣳⣴⣵⣶⣷⣸⣹⣺⣻⣼⣽⣾
func (b Braille) String() string {
return string(b.Rune())
}
type BrailleFlusher struct{}
func (BrailleFlusher) Flush(w io.Writer, img image.Image) error {
// An image's bounds do not necessarily start at (0, 0), so the two loops start
// at bounds.Min.Y and bounds.Min.X.
// Looping over Y first and X second is more likely to result in better memory
// access patterns than X first and Y second.
bounds := img.Bounds()
for py := bounds.Min.Y; py < bounds.Max.Y; py += 4 {
for px := bounds.Min.X; px < bounds.Max.X; px += 2 {
var b Braille
// Draw left-right, top-bottom.
for y := 0; y < 4; y++ {
for x := 0; x < 2; x++ {
if px+x >= bounds.Max.X || py+y >= bounds.Max.Y {
continue
}
// Always bet on black!
if img.At(px+x, py+y) == color.Black {
b[x][y] = 1
}
}
}
if _, err := w.Write([]byte(b.String())); err != nil {
return err
}
}
if _, err := w.Write([]byte{'\n'}); err != nil {
return err
}
}
return nil
}