package main import ( "fmt" "github.com/boombuler/barcode/qr" "image" "image/color" "os" "strings" ) type utf8r rune func (u utf8r) String(html bool) string { f := "%c" if html { f = "&#x%x;" } return fmt.Sprintf(f, u) } const blank rune = ' ' // U+0020 const upper rune = '▀' // U+2580 const lower rune = '▄' // U+2584 const whole rune = '█' // U+2588 var block = [6]rune{blank, upper, lower, whole, lower, whole} var bw = []color.Color{color.Black, color.White, color.White, color.White} var bwp = color.Palette(bw) func pad(n int, r ...rune) string { if n <= 1 { n += 1 } if len(r) == 0 { return strings.Repeat(utf8r(whole).String(false), n) } return strings.Repeat(utf8r(r[0]).String(false), n) } func getblock(img image.Image, x int, y int, yn int) utf8r { // fmt.Printf("%v ", image.Pt(x, y+1).In(img.Bounds())) return utf8r(block[((bwp.Index(img.At(x, y)))+2*bwp.Index(img.At(x, y+1)))+2*(yn%2)]) } /*.Intersect(image.Rect(x, y, x+1, y+2))*/ func xys(img image.Image, y *int) any { un := img.Bounds().Intersect(image.Rect(img.Bounds().Min.X, *y, img.Bounds().Max.X, *y+2)).Size().Y *y = *y + un return un // return image.Rect(x, y, x+1, y+2).Intersect(img.Bounds().Union(image.Rect(0, 0, 1, 2))) } func qrstr(img image.Image, html bool) string { var b string = "" var y, i int = 0, 0 yn := 2 for 1 <= yn { yn = xys(img, &y).(int) for i = 0; i < img.Bounds().Size().X; i++ { b += getblock(img, i, y-yn, yn).String(html) } if yn <= 1 { break } b += "\n" } if html { b = "" + strings.ReplaceAll(b, "\n", "") b = strings.TrimSuffix(b, "") b = `` + b + "
" } else { b = strings.ReplaceAll(b, "\n", pad(1)+"\n"+pad(1)) b = strings.TrimPrefix(b, pad(1)+"\n") + pad(1) b = pad(0) + pad(img.Bounds().Dx()+2, whole) + pad(0) + "\n" + pad(1) + b + "\n" b += pad(img.Bounds().Dx()+4, whole) } return b } func wrap(s string, w int) []string { s = strings.Join(strings.Split(s, " "), "\n") var b = strings.Split(s, "\n") var line = "" var lines []string for i, v := range b { if len(v) > w { lines = append(lines, v[:w-1], v[w-1:]) continue } if len(line)+len(v) < w { line += v + " " } if len(line)+len(v) >= w { lines = append(lines, strings.TrimSuffix(line, " ")) line = "" } if i == len(b)-1 { lines = append(lines, strings.TrimSuffix(line, " ")) } } return lines } func encodeqr(s string, header bool, html bool) (string, error) { bar, err := qr.Encode(s, qr.L, qr.Auto) if err != nil { return "", err } var output = "" if header && !html { width := bar.Bounds().Dx() ar := wrap(s, width) output += fmt.Sprintln(pad(0, whole) + pad(width+2, upper) + pad(0, whole)) for i, v := range ar { v = pad((((width)-len(v)-1*2*(1-width%2))/2)-(width%2), blank) + v + pad((width-len(v)+2+2*(width%2))/2, blank) v = pad(0) + pad(0, blank) + v + pad(0) output += fmt.Sprintf("%s", v) if i < len(ar) { output += fmt.Sprintln() } } output += fmt.Sprintln(pad(0, whole) + pad(width+2, lower) + pad(0, whole)) } else if header && html { output += fmt.Sprintf("

%s

", s) } output += fmt.Sprintln(qrstr(bar, html)) return output, nil } func main() { fmt.Println(encodeqr(strings.Join(os.Args[1:], " "), true, false)) }