gitee.com/quant1x/gox@v1.7.6/qrterminal/qrterminal.go (about)

     1  package qrterminal
     2  
     3  import (
     4  	"io"
     5  	"strings"
     6  
     7  	"rsc.io/qr"
     8  )
     9  
    10  const WHITE = "\033[47m  \033[0m"
    11  const BLACK = "\033[40m  \033[0m"
    12  
    13  // Use ascii blocks to form the QR Code
    14  const BLACK_WHITE = "▄"
    15  const BLACK_BLACK = " "
    16  const WHITE_BLACK = "▀"
    17  const WHITE_WHITE = "█"
    18  
    19  // Level - the QR Code's redundancy level
    20  const H = qr.H
    21  const M = qr.M
    22  const L = qr.L
    23  
    24  // default is 4-pixel-wide white quiet zone
    25  const QUIET_ZONE = 4
    26  
    27  //Config for generating a barcode
    28  type Config struct {
    29  	Level          qr.Level
    30  	Writer         io.Writer
    31  	HalfBlocks     bool
    32  	BlackChar      string
    33  	BlackWhiteChar string
    34  	WhiteChar      string
    35  	WhiteBlackChar string
    36  	QuietZone      int
    37  }
    38  
    39  func (c *Config) writeFullBlocks(w io.Writer, code *qr.Code) {
    40  	white := c.WhiteChar
    41  	black := c.BlackChar
    42  
    43  	// Frame the barcode in a 1 pixel border
    44  	w.Write([]byte(stringRepeat(stringRepeat(white,
    45  		code.Size+c.QuietZone*2)+"\n", c.QuietZone))) // top border
    46  	for i := 0; i <= code.Size; i++ {
    47  		w.Write([]byte(stringRepeat(white, c.QuietZone))) // left border
    48  		for j := 0; j <= code.Size; j++ {
    49  			if code.Black(j, i) {
    50  				w.Write([]byte(black))
    51  			} else {
    52  				w.Write([]byte(white))
    53  			}
    54  		}
    55  		w.Write([]byte(stringRepeat(white, c.QuietZone-1) + "\n")) // right border
    56  	}
    57  	w.Write([]byte(stringRepeat(stringRepeat(white,
    58  		code.Size+c.QuietZone*2)+"\n", c.QuietZone-1))) // bottom border
    59  }
    60  
    61  func (c *Config) writeHalfBlocks(w io.Writer, code *qr.Code) {
    62  	ww := c.WhiteChar
    63  	bb := c.BlackChar
    64  	wb := c.WhiteBlackChar
    65  	bw := c.BlackWhiteChar
    66  	// Frame the barcode in a 4 pixel border
    67  	// top border
    68  	if c.QuietZone%2 != 0 {
    69  		w.Write([]byte(stringRepeat(bw, code.Size+c.QuietZone*2) + "\n"))
    70  		w.Write([]byte(stringRepeat(stringRepeat(ww,
    71  			code.Size+c.QuietZone*2)+"\n", c.QuietZone/2)))
    72  	} else {
    73  		w.Write([]byte(stringRepeat(stringRepeat(ww,
    74  			code.Size+c.QuietZone*2)+"\n", c.QuietZone/2)))
    75  	}
    76  	for i := 0; i <= code.Size; i += 2 {
    77  		w.Write([]byte(stringRepeat(ww, c.QuietZone))) // left border
    78  		for j := 0; j <= code.Size; j++ {
    79  			next_black := false
    80  			if i+1 < code.Size {
    81  				next_black = code.Black(j, i+1)
    82  			}
    83  			curr_black := code.Black(j, i)
    84  			if curr_black && next_black {
    85  				w.Write([]byte(bb))
    86  			} else if curr_black && !next_black {
    87  				w.Write([]byte(bw))
    88  			} else if !curr_black && !next_black {
    89  				w.Write([]byte(ww))
    90  			} else {
    91  				w.Write([]byte(wb))
    92  			}
    93  		}
    94  		w.Write([]byte(stringRepeat(ww, c.QuietZone-1) + "\n")) // right border
    95  	}
    96  	// bottom border
    97  	if c.QuietZone%2 == 0 {
    98  		w.Write([]byte(stringRepeat(stringRepeat(ww,
    99  			code.Size+c.QuietZone*2)+"\n", c.QuietZone/2-1)))
   100  		w.Write([]byte(stringRepeat(wb, code.Size+c.QuietZone*2) + "\n"))
   101  	} else {
   102  		w.Write([]byte(stringRepeat(stringRepeat(ww,
   103  			code.Size+c.QuietZone*2)+"\n", c.QuietZone/2)))
   104  	}
   105  }
   106  
   107  func stringRepeat(s string, count int) string {
   108  	if count <= 0 {
   109  		return ""
   110  	}
   111  	return strings.Repeat(s, count)
   112  }
   113  
   114  // GenerateWithConfig expects a string to encode and a config
   115  func GenerateWithConfig(text string, config Config) {
   116  	if config.QuietZone < 1 {
   117  		config.QuietZone = 1 // at least 1-pixel-wide white quiet zone
   118  	}
   119  	w := config.Writer
   120  	code, _ := qr.Encode(text, config.Level)
   121  	if config.HalfBlocks {
   122  		config.writeHalfBlocks(w, code)
   123  	} else {
   124  		config.writeFullBlocks(w, code)
   125  	}
   126  }
   127  
   128  // Generate a QR Code and write it out to io.Writer
   129  func Generate(text string, l qr.Level, w io.Writer) {
   130  	config := Config{
   131  		Level:     l,
   132  		Writer:    w,
   133  		BlackChar: BLACK,
   134  		WhiteChar: WHITE,
   135  		QuietZone: QUIET_ZONE,
   136  	}
   137  	GenerateWithConfig(text, config)
   138  }
   139  
   140  // Generate a QR Code with half blocks and write it out to io.Writer
   141  func GenerateHalfBlock(text string, l qr.Level, w io.Writer) {
   142  	config := Config{
   143  		Level:          l,
   144  		Writer:         w,
   145  		HalfBlocks:     true,
   146  		BlackChar:      BLACK_BLACK,
   147  		WhiteBlackChar: WHITE_BLACK,
   148  		WhiteChar:      WHITE_WHITE,
   149  		BlackWhiteChar: BLACK_WHITE,
   150  		QuietZone:      QUIET_ZONE,
   151  	}
   152  	GenerateWithConfig(text, config)
   153  }