You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
3.8 KiB
Go
156 lines
3.8 KiB
Go
6 years ago
|
package qrcodeTerminal
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
|
||
|
"github.com/skip2/go-qrcode"
|
||
|
"github.com/mattn/go-colorable"
|
||
|
"image/png"
|
||
|
nbytes "bytes"
|
||
|
)
|
||
|
|
||
|
type consoleColor string
|
||
|
type consoleColors struct {
|
||
|
NormalBlack consoleColor
|
||
|
NormalRed consoleColor
|
||
|
NormalGreen consoleColor
|
||
|
NormalYellow consoleColor
|
||
|
NormalBlue consoleColor
|
||
|
NormalMagenta consoleColor
|
||
|
NormalCyan consoleColor
|
||
|
NormalWhite consoleColor
|
||
|
BrightBlack consoleColor
|
||
|
BrightRed consoleColor
|
||
|
BrightGreen consoleColor
|
||
|
BrightYellow consoleColor
|
||
|
BrightBlue consoleColor
|
||
|
BrightMagenta consoleColor
|
||
|
BrightCyan consoleColor
|
||
|
BrightWhite consoleColor
|
||
|
}
|
||
|
type qrcodeRecoveryLevel qrcode.RecoveryLevel
|
||
|
type qrcodeRecoveryLevels struct {
|
||
|
Low qrcodeRecoveryLevel
|
||
|
Medium qrcodeRecoveryLevel
|
||
|
High qrcodeRecoveryLevel
|
||
|
Highest qrcodeRecoveryLevel
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
ConsoleColors consoleColors = consoleColors{
|
||
|
NormalBlack: "\033[38;5;0m \033[0m",
|
||
|
NormalRed: "\033[38;5;1m \033[0m",
|
||
|
NormalGreen: "\033[38;5;2m \033[0m",
|
||
|
NormalYellow: "\033[38;5;3m \033[0m",
|
||
|
NormalBlue: "\033[38;5;4m \033[0m",
|
||
|
NormalMagenta: "\033[38;5;5m \033[0m",
|
||
|
NormalCyan: "\033[38;5;6m \033[0m",
|
||
|
NormalWhite: "\033[38;5;7m \033[0m",
|
||
|
BrightBlack: "\033[48;5;0m \033[0m",
|
||
|
BrightRed: "\033[48;5;1m \033[0m",
|
||
|
BrightGreen: "\033[48;5;2m \033[0m",
|
||
|
BrightYellow: "\033[48;5;3m \033[0m",
|
||
|
BrightBlue: "\033[48;5;4m \033[0m",
|
||
|
BrightMagenta: "\033[48;5;5m \033[0m",
|
||
|
BrightCyan: "\033[48;5;6m \033[0m",
|
||
|
BrightWhite: "\033[48;5;7m \033[0m"}
|
||
|
QRCodeRecoveryLevels = qrcodeRecoveryLevels{
|
||
|
Low: qrcodeRecoveryLevel(qrcode.Low),
|
||
|
Medium: qrcodeRecoveryLevel(qrcode.Medium),
|
||
|
High: qrcodeRecoveryLevel(qrcode.High),
|
||
|
Highest: qrcodeRecoveryLevel(qrcode.Highest)}
|
||
|
)
|
||
|
|
||
|
type QRCodeString string
|
||
|
|
||
|
func (v *QRCodeString) Print() {
|
||
|
fmt.Fprint(outer, *v)
|
||
|
}
|
||
|
|
||
|
type qrcodeTerminal struct {
|
||
|
front consoleColor
|
||
|
back consoleColor
|
||
|
level qrcodeRecoveryLevel
|
||
|
}
|
||
|
|
||
|
func (v *qrcodeTerminal) Get(content interface{}) (result *QRCodeString) {
|
||
|
var qr *qrcode.QRCode
|
||
|
var err error
|
||
|
if t, ok := content.(string); ok {
|
||
|
qr, err = qrcode.New(t, qrcode.RecoveryLevel(v.level))
|
||
|
} else if t, ok := content.([]byte); ok {
|
||
|
qr, err = qrcode.New(string(t), qrcode.RecoveryLevel(v.level))
|
||
|
}
|
||
|
if qr != nil && err == nil {
|
||
|
data := qr.Bitmap()
|
||
|
result = v.getQRCodeString(data)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (v *qrcodeTerminal) Get2(bytes []byte) (result *QRCodeString) {
|
||
|
data, err := parseQR(bytes)
|
||
|
if err == nil {
|
||
|
result = v.getQRCodeString(data)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func New2(front, back consoleColor, level qrcodeRecoveryLevel) *qrcodeTerminal {
|
||
|
obj := qrcodeTerminal{front: front, back: back, level: level}
|
||
|
return &obj
|
||
|
}
|
||
|
|
||
|
func New() *qrcodeTerminal {
|
||
|
front, back, level := ConsoleColors.BrightBlack, ConsoleColors.BrightWhite, QRCodeRecoveryLevels.Medium
|
||
|
return New2(front, back, level)
|
||
|
}
|
||
|
|
||
|
func (v *qrcodeTerminal) getQRCodeString(data [][]bool) (result *QRCodeString) {
|
||
|
str := ""
|
||
|
for ir, row := range data {
|
||
|
lr := len(row)
|
||
|
if ir == 0 || ir == 1 || ir == 2 ||
|
||
|
ir == lr-1 || ir == lr-2 || ir == lr-3 {
|
||
|
continue
|
||
|
}
|
||
|
for ic, col := range row {
|
||
|
lc := len(data)
|
||
|
if ic == 0 || ic == 1 || ic == 2 ||
|
||
|
ic == lc-1 || ic == lc-2 || ic == lc-3 {
|
||
|
continue
|
||
|
}
|
||
|
if col {
|
||
|
str += fmt.Sprint(v.front)
|
||
|
} else {
|
||
|
str += fmt.Sprint(v.back)
|
||
|
}
|
||
|
}
|
||
|
str += fmt.Sprintln()
|
||
|
}
|
||
|
obj := QRCodeString(str)
|
||
|
result = &obj
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func parseQR(bytes []byte) (data [][]bool, err error) {
|
||
|
r := nbytes.NewReader(bytes)
|
||
|
img, err := png.Decode(r)
|
||
|
if err == nil {
|
||
|
rect := img.Bounds()
|
||
|
mx, my := rect.Max.X, rect.Max.Y
|
||
|
data = make([][]bool, mx)
|
||
|
for x := 0; x < mx; x++ {
|
||
|
data[x] = make([]bool, my)
|
||
|
for y := 0; y < my; y++ {
|
||
|
c := img.At(x, y)
|
||
|
r, _, _, _ := c.RGBA()
|
||
|
data[x][y] = r == 0
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var outer = colorable.NewColorableStdout()
|