forked from tmpim/juroku
/
cc.go
86 lines (71 loc) · 1.76 KB
/
cc.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
75
76
77
78
79
80
81
82
83
84
85
86
package juroku
import (
"bytes"
"errors"
"image"
"image/color"
)
var colorAlphabet = "0123456789abcdef"
// GenerateFrameChunk generates a frame chunk for the given image.
func GenerateFrameChunk(img image.Image) (*FrameChunk, error) {
palette := GetPalette(img)
if len(palette) > 16 {
return nil, errors.New("juroku: GenerateFrameChunk: palette must have <= 16 colors")
}
frame := &FrameChunk{
Width: img.Bounds().Dx() / 2,
Height: img.Bounds().Dy() / 3,
}
paletteToColor := make(map[color.RGBA]byte)
for i, col := range palette {
paletteToColor[col.(color.RGBA)] = byte(i)
}
for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y += 3 {
row := FrameRow{
TextColor: new(bytes.Buffer),
BackgroundColor: new(bytes.Buffer),
Text: new(bytes.Buffer),
}
for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x += 2 {
chunk := make([]byte, 0, 6)
for dy := 0; dy < 3; dy++ {
for dx := 0; dx < 2; dx++ {
chunk = append(chunk,
paletteToColor[img.At(x+dx, y+dy).(color.RGBA)])
}
}
text, textColor, bgColor := chunkToBlit(chunk)
row.TextColor.WriteByte(colorAlphabet[textColor])
row.BackgroundColor.WriteByte(colorAlphabet[bgColor])
row.Text.WriteByte(text)
}
frame.Rows = append(frame.Rows, row)
}
for i := range frame.Palette {
if len(palette) <= i {
// Unused color
frame.Palette[i] = color.RGBA{}
} else {
frame.Palette[i] = palette[i].(color.RGBA)
}
}
return frame, nil
}
func chunkToBlit(chunk []byte) (char byte, textColor byte, bgColor byte) {
bgColor = chunk[5]
var b byte
var i byte
for i = 0; i < 6; i++ {
if chunk[i] != bgColor {
textColor = chunk[i]
b |= 1 << i
} else {
b |= 0 << i
}
}
if textColor == 0 {
textColor = '0'
}
char = b + 128
return
}