Implement QR code display via unicode block characters.

Use `--draw` to use ANSImage instead which is less compatible with
legacy or remote terminals.
master
Icedream 2017-09-04 11:22:56 +02:00
parent cf68a4548f
commit 800d9897ff
Signed by: icedream
GPG Key ID: 1573F6D8EFE4D0CF
2 changed files with 108 additions and 1 deletions

View File

@ -0,0 +1,87 @@
package internal
import (
"io"
"strings"
"github.com/fatih/color"
"github.com/qpliu/qrencode-go/qrencode"
)
const (
Upper byte = 1 << iota
Lower
)
var (
// Got the information from https://de.wikipedia.org/wiki/Unicodeblock_Blockelemente
byteMapping = map[byte]rune{
0: ' ',
Upper: '\u2580', // UPPER HALF BLOCK
Lower: '\u2584', // LOWER HALF BLOCK
Upper | Lower: '\u2588', // FULL BLOCK
}
)
func ConvertGridToUnicode(target io.Writer, source *qrencode.BitGrid) (err error) {
c := color.New(color.BgWhite)
c.Add(color.FgBlack)
writeSpaceLine := func() (n int, err error) {
n, err = c.Fprint(target, strings.Repeat(" ", source.Width()+2))
if err != nil {
return
}
m, err := target.Write([]byte{'\n'})
if err != nil {
return
}
n += m
return
}
if _, err = writeSpaceLine(); err != nil {
return
}
for y := 0; y < source.Height(); y += 2 {
// Go from left to right in both rows
line := " "
for x := 0; x < source.Width(); x++ {
var runeKey byte
// First row
if source.Get(x, y) {
runeKey |= Upper
}
if y+1 < source.Height() {
if source.Get(x, y+1) {
runeKey |= Lower
}
}
line += string(byteMapping[runeKey])
}
line += " "
_, err = c.Fprint(target, line)
if err != nil {
return
}
_, err = target.Write([]byte{'\n'})
if err != nil {
return
}
}
if err == io.EOF {
err = nil
}
_, err = writeSpaceLine()
return
}

22
main.go
View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"bytes"
"encoding/base32" "encoding/base32"
"errors" "errors"
"fmt" "fmt"
@ -48,6 +49,9 @@ var (
var ( var (
app = kingpin.New("pixelqr", "Generates QR code from any input and displays it in your ANSI true-color compatible terminal.") app = kingpin.New("pixelqr", "Generates QR code from any input and displays it in your ANSI true-color compatible terminal.")
flagANSImage = app.Flag("draw", "Use ANSI drawing code using ANSImage.").
Default("false").
Bool()
flagECLevel = app.Flag("ec", "Sets the error correction level for the generated code."). flagECLevel = app.Flag("ec", "Sets the error correction level for the generated code.").
Default(ECLevel_L). Default(ECLevel_L).
Enum(ECLevel_L, ECLevel_M, ECLevel_Q, ECLevel_H) Enum(ECLevel_L, ECLevel_M, ECLevel_Q, ECLevel_H)
@ -162,7 +166,23 @@ func generateCliQR(input string) (err error) {
return return
} }
s, err := internal.ConvertGridToANSImage(grid) var s string
if *flagANSImage {
s, err = internal.ConvertGridToANSImage(grid)
if err != nil {
return
}
} else {
w := new(bytes.Buffer)
err = internal.ConvertGridToUnicode(w, grid)
if err != nil {
return
}
s = string(w.Bytes())
}
fmt.Println(s) fmt.Println(s)