diff options
Diffstat (limited to 'vendor/github.com/skip2/go-qrcode/qrcode.go')
-rw-r--r-- | vendor/github.com/skip2/go-qrcode/qrcode.go | 608 |
1 files changed, 0 insertions, 608 deletions
diff --git a/vendor/github.com/skip2/go-qrcode/qrcode.go b/vendor/github.com/skip2/go-qrcode/qrcode.go deleted file mode 100644 index d0541bcb..00000000 --- a/vendor/github.com/skip2/go-qrcode/qrcode.go +++ /dev/null @@ -1,608 +0,0 @@ -// go-qrcode -// Copyright 2014 Tom Harwood - -/* -Package qrcode implements a QR Code encoder. - -A QR Code is a matrix (two-dimensional) barcode. Arbitrary content may be -encoded. - -A QR Code contains error recovery information to aid reading damaged or -obscured codes. There are four levels of error recovery: qrcode.{Low, Medium, -High, Highest}. QR Codes with a higher recovery level are more robust to damage, -at the cost of being physically larger. - -Three functions cover most use cases: - -- Create a PNG image: - - var png []byte - png, err := qrcode.Encode("https://example.org", qrcode.Medium, 256) - -- Create a PNG image and write to a file: - - err := qrcode.WriteFile("https://example.org", qrcode.Medium, 256, "qr.png") - -- Create a PNG image with custom colors and write to file: - - err := qrcode.WriteColorFile("https://example.org", qrcode.Medium, 256, color.Black, color.White, "qr.png") - -All examples use the qrcode.Medium error Recovery Level and create a fixed -256x256px size QR Code. The last function creates a white on black instead of black -on white QR Code. - -To generate a variable sized image instead, specify a negative size (in place of -the 256 above), such as -4 or -5. Larger negative numbers create larger images: -A size of -5 sets each module (QR Code "pixel") to be 5px wide/high. - -- Create a PNG image (variable size, with minimum white padding) and write to a file: - - err := qrcode.WriteFile("https://example.org", qrcode.Medium, -5, "qr.png") - -The maximum capacity of a QR Code varies according to the content encoded and -the error recovery level. The maximum capacity is 2,953 bytes, 4,296 -alphanumeric characters, 7,089 numeric digits, or a combination of these. - -This package implements a subset of QR Code 2005, as defined in ISO/IEC -18004:2006. -*/ -package qrcode - -import ( - "bytes" - "errors" - "fmt" - "image" - "image/color" - "image/png" - "io" - "io/ioutil" - "log" - "os" - - bitset "github.com/skip2/go-qrcode/bitset" - reedsolomon "github.com/skip2/go-qrcode/reedsolomon" -) - -// Encode a QR Code and return a raw PNG image. -// -// size is both the image width and height in pixels. If size is too small then -// a larger image is silently returned. Negative values for size cause a -// variable sized image to be returned: See the documentation for Image(). -// -// To serve over HTTP, remember to send a Content-Type: image/png header. -func Encode(content string, level RecoveryLevel, size int) ([]byte, error) { - var q *QRCode - - q, err := New(content, level) - - if err != nil { - return nil, err - } - - return q.PNG(size) -} - -// WriteFile encodes, then writes a QR Code to the given filename in PNG format. -// -// size is both the image width and height in pixels. If size is too small then -// a larger image is silently written. Negative values for size cause a variable -// sized image to be written: See the documentation for Image(). -func WriteFile(content string, level RecoveryLevel, size int, filename string) error { - var q *QRCode - - q, err := New(content, level) - - if err != nil { - return err - } - - return q.WriteFile(size, filename) -} - -// WriteColorFile encodes, then writes a QR Code to the given filename in PNG format. -// With WriteColorFile you can also specify the colors you want to use. -// -// size is both the image width and height in pixels. If size is too small then -// a larger image is silently written. Negative values for size cause a variable -// sized image to be written: See the documentation for Image(). -func WriteColorFile(content string, level RecoveryLevel, size int, background, - foreground color.Color, filename string) error { - - var q *QRCode - - q, err := New(content, level) - - q.BackgroundColor = background - q.ForegroundColor = foreground - - if err != nil { - return err - } - - return q.WriteFile(size, filename) -} - -// A QRCode represents a valid encoded QRCode. -type QRCode struct { - // Original content encoded. - Content string - - // QR Code type. - Level RecoveryLevel - VersionNumber int - - // User settable drawing options. - ForegroundColor color.Color - BackgroundColor color.Color - - // Disable the QR Code border. - DisableBorder bool - - encoder *dataEncoder - version qrCodeVersion - - data *bitset.Bitset - symbol *symbol - mask int -} - -// New constructs a QRCode. -// -// var q *qrcode.QRCode -// q, err := qrcode.New("my content", qrcode.Medium) -// -// An error occurs if the content is too long. -func New(content string, level RecoveryLevel) (*QRCode, error) { - encoders := []dataEncoderType{dataEncoderType1To9, dataEncoderType10To26, - dataEncoderType27To40} - - var encoder *dataEncoder - var encoded *bitset.Bitset - var chosenVersion *qrCodeVersion - var err error - - for _, t := range encoders { - encoder = newDataEncoder(t) - encoded, err = encoder.encode([]byte(content)) - - if err != nil { - continue - } - - chosenVersion = chooseQRCodeVersion(level, encoder, encoded.Len()) - - if chosenVersion != nil { - break - } - } - - if err != nil { - return nil, err - } else if chosenVersion == nil { - return nil, errors.New("content too long to encode") - } - - q := &QRCode{ - Content: content, - - Level: level, - VersionNumber: chosenVersion.version, - - ForegroundColor: color.Black, - BackgroundColor: color.White, - - encoder: encoder, - data: encoded, - version: *chosenVersion, - } - - return q, nil -} - -// NewWithForcedVersion constructs a QRCode of a specific version. -// -// var q *qrcode.QRCode -// q, err := qrcode.NewWithForcedVersion("my content", 25, qrcode.Medium) -// -// An error occurs in case of invalid version. -func NewWithForcedVersion(content string, version int, level RecoveryLevel) (*QRCode, error) { - var encoder *dataEncoder - - switch { - case version >= 1 && version <= 9: - encoder = newDataEncoder(dataEncoderType1To9) - case version >= 10 && version <= 26: - encoder = newDataEncoder(dataEncoderType10To26) - case version >= 27 && version <= 40: - encoder = newDataEncoder(dataEncoderType27To40) - default: - return nil, fmt.Errorf("Invalid version %d (expected 1-40 inclusive)", version) - } - - var encoded *bitset.Bitset - encoded, err := encoder.encode([]byte(content)) - - if err != nil { - return nil, err - } - - chosenVersion := getQRCodeVersion(level, version) - - if chosenVersion == nil { - return nil, errors.New("cannot find QR Code version") - } - - if encoded.Len() > chosenVersion.numDataBits() { - return nil, fmt.Errorf("Cannot encode QR code: content too large for fixed size QR Code version %d (encoded length is %d bits, maximum length is %d bits)", - version, - encoded.Len(), - chosenVersion.numDataBits()) - } - - q := &QRCode{ - Content: content, - - Level: level, - VersionNumber: chosenVersion.version, - - ForegroundColor: color.Black, - BackgroundColor: color.White, - - encoder: encoder, - data: encoded, - version: *chosenVersion, - } - - return q, nil -} - -// Bitmap returns the QR Code as a 2D array of 1-bit pixels. -// -// bitmap[y][x] is true if the pixel at (x, y) is set. -// -// The bitmap includes the required "quiet zone" around the QR Code to aid -// decoding. -func (q *QRCode) Bitmap() [][]bool { - // Build QR code. - q.encode() - - return q.symbol.bitmap() -} - -// Image returns the QR Code as an image.Image. -// -// A positive size sets a fixed image width and height (e.g. 256 yields an -// 256x256px image). -// -// Depending on the amount of data encoded, fixed size images can have different -// amounts of padding (white space around the QR Code). As an alternative, a -// variable sized image can be generated instead: -// -// A negative size causes a variable sized image to be returned. The image -// returned is the minimum size required for the QR Code. Choose a larger -// negative number to increase the scale of the image. e.g. a size of -5 causes -// each module (QR Code "pixel") to be 5px in size. -func (q *QRCode) Image(size int) image.Image { - // Build QR code. - q.encode() - - // Minimum pixels (both width and height) required. - realSize := q.symbol.size - - // Variable size support. - if size < 0 { - size = size * -1 * realSize - } - - // Actual pixels available to draw the symbol. Automatically increase the - // image size if it's not large enough. - if size < realSize { - size = realSize - } - - // Output image. - rect := image.Rectangle{Min: image.Point{0, 0}, Max: image.Point{size, size}} - - // Saves a few bytes to have them in this order - p := color.Palette([]color.Color{q.BackgroundColor, q.ForegroundColor}) - img := image.NewPaletted(rect, p) - fgClr := uint8(img.Palette.Index(q.ForegroundColor)) - - // QR code bitmap. - bitmap := q.symbol.bitmap() - - // Map each image pixel to the nearest QR code module. - modulesPerPixel := float64(realSize) / float64(size) - for y := 0; y < size; y++ { - y2 := int(float64(y) * modulesPerPixel) - for x := 0; x < size; x++ { - x2 := int(float64(x) * modulesPerPixel) - - v := bitmap[y2][x2] - - if v { - pos := img.PixOffset(x, y) - img.Pix[pos] = fgClr - } - } - } - - return img -} - -// PNG returns the QR Code as a PNG image. -// -// size is both the image width and height in pixels. If size is too small then -// a larger image is silently returned. Negative values for size cause a -// variable sized image to be returned: See the documentation for Image(). -func (q *QRCode) PNG(size int) ([]byte, error) { - img := q.Image(size) - - encoder := png.Encoder{CompressionLevel: png.BestCompression} - - var b bytes.Buffer - err := encoder.Encode(&b, img) - - if err != nil { - return nil, err - } - - return b.Bytes(), nil -} - -// Write writes the QR Code as a PNG image to io.Writer. -// -// size is both the image width and height in pixels. If size is too small then -// a larger image is silently written. Negative values for size cause a -// variable sized image to be written: See the documentation for Image(). -func (q *QRCode) Write(size int, out io.Writer) error { - var png []byte - - png, err := q.PNG(size) - - if err != nil { - return err - } - _, err = out.Write(png) - return err -} - -// WriteFile writes the QR Code as a PNG image to the specified file. -// -// size is both the image width and height in pixels. If size is too small then -// a larger image is silently written. Negative values for size cause a -// variable sized image to be written: See the documentation for Image(). -func (q *QRCode) WriteFile(size int, filename string) error { - var png []byte - - png, err := q.PNG(size) - - if err != nil { - return err - } - - return ioutil.WriteFile(filename, png, os.FileMode(0644)) -} - -// encode completes the steps required to encode the QR Code. These include -// adding the terminator bits and padding, splitting the data into blocks and -// applying the error correction, and selecting the best data mask. -func (q *QRCode) encode() { - numTerminatorBits := q.version.numTerminatorBitsRequired(q.data.Len()) - - q.addTerminatorBits(numTerminatorBits) - q.addPadding() - - encoded := q.encodeBlocks() - - const numMasks int = 8 - penalty := 0 - - for mask := 0; mask < numMasks; mask++ { - var s *symbol - var err error - - s, err = buildRegularSymbol(q.version, mask, encoded, !q.DisableBorder) - - if err != nil { - log.Panic(err.Error()) - } - - numEmptyModules := s.numEmptyModules() - if numEmptyModules != 0 { - log.Panicf("bug: numEmptyModules is %d (expected 0) (version=%d)", - numEmptyModules, q.VersionNumber) - } - - p := s.penaltyScore() - - //log.Printf("mask=%d p=%3d p1=%3d p2=%3d p3=%3d p4=%d\n", mask, p, s.penalty1(), s.penalty2(), s.penalty3(), s.penalty4()) - - if q.symbol == nil || p < penalty { - q.symbol = s - q.mask = mask - penalty = p - } - } -} - -// addTerminatorBits adds final terminator bits to the encoded data. -// -// The number of terminator bits required is determined when the QR Code version -// is chosen (which itself depends on the length of the data encoded). The -// terminator bits are thus added after the QR Code version -// is chosen, rather than at the data encoding stage. -func (q *QRCode) addTerminatorBits(numTerminatorBits int) { - q.data.AppendNumBools(numTerminatorBits, false) -} - -// encodeBlocks takes the completed (terminated & padded) encoded data, splits -// the data into blocks (as specified by the QR Code version), applies error -// correction to each block, then interleaves the blocks together. -// -// The QR Code's final data sequence is returned. -func (q *QRCode) encodeBlocks() *bitset.Bitset { - // Split into blocks. - type dataBlock struct { - data *bitset.Bitset - ecStartOffset int - } - - block := make([]dataBlock, q.version.numBlocks()) - - start := 0 - end := 0 - blockID := 0 - - for _, b := range q.version.block { - for j := 0; j < b.numBlocks; j++ { - start = end - end = start + b.numDataCodewords*8 - - // Apply error correction to each block. - numErrorCodewords := b.numCodewords - b.numDataCodewords - block[blockID].data = reedsolomon.Encode(q.data.Substr(start, end), numErrorCodewords) - block[blockID].ecStartOffset = end - start - - blockID++ - } - } - - // Interleave the blocks. - - result := bitset.New() - - // Combine data blocks. - working := true - for i := 0; working; i += 8 { - working = false - - for j, b := range block { - if i >= block[j].ecStartOffset { - continue - } - - result.Append(b.data.Substr(i, i+8)) - - working = true - } - } - - // Combine error correction blocks. - working = true - for i := 0; working; i += 8 { - working = false - - for j, b := range block { - offset := i + block[j].ecStartOffset - if offset >= block[j].data.Len() { - continue - } - - result.Append(b.data.Substr(offset, offset+8)) - - working = true - } - } - - // Append remainder bits. - result.AppendNumBools(q.version.numRemainderBits, false) - - return result -} - -// max returns the maximum of a and b. -func max(a int, b int) int { - if a > b { - return a - } - - return b -} - -// addPadding pads the encoded data upto the full length required. -func (q *QRCode) addPadding() { - numDataBits := q.version.numDataBits() - - if q.data.Len() == numDataBits { - return - } - - // Pad to the nearest codeword boundary. - q.data.AppendNumBools(q.version.numBitsToPadToCodeword(q.data.Len()), false) - - // Pad codewords 0b11101100 and 0b00010001. - padding := [2]*bitset.Bitset{ - bitset.New(true, true, true, false, true, true, false, false), - bitset.New(false, false, false, true, false, false, false, true), - } - - // Insert pad codewords alternately. - i := 0 - for numDataBits-q.data.Len() >= 8 { - q.data.Append(padding[i]) - - i = 1 - i // Alternate between 0 and 1. - } - - if q.data.Len() != numDataBits { - log.Panicf("BUG: got len %d, expected %d", q.data.Len(), numDataBits) - } -} - -// ToString produces a multi-line string that forms a QR-code image. -func (q *QRCode) ToString(inverseColor bool) string { - bits := q.Bitmap() - var buf bytes.Buffer - for y := range bits { - for x := range bits[y] { - if bits[y][x] != inverseColor { - buf.WriteString(" ") - } else { - buf.WriteString("██") - } - } - buf.WriteString("\n") - } - return buf.String() -} - -// ToSmallString produces a multi-line string that forms a QR-code image, a -// factor two smaller in x and y then ToString. -func (q *QRCode) ToSmallString(inverseColor bool) string { - bits := q.Bitmap() - var buf bytes.Buffer - // if there is an odd number of rows, the last one needs special treatment - for y := 0; y < len(bits)-1; y += 2 { - for x := range bits[y] { - if bits[y][x] == bits[y+1][x] { - if bits[y][x] != inverseColor { - buf.WriteString(" ") - } else { - buf.WriteString("█") - } - } else { - if bits[y][x] != inverseColor { - buf.WriteString("▄") - } else { - buf.WriteString("▀") - } - } - } - buf.WriteString("\n") - } - // special treatment for the last row if odd - if len(bits)%2 == 1 { - y := len(bits) - 1 - for x := range bits[y] { - if bits[y][x] != inverseColor { - buf.WriteString(" ") - } else { - buf.WriteString("▀") - } - } - buf.WriteString("\n") - } - return buf.String() -} |