// Copyright 2011 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.
// Package coding implements low-level QR coding details.
package coding // import "rsc.io/qr/coding"import ()// Field is the field for QR error correction.varField = gf256.NewField(0x11d, 2)// A Version represents a QR version.// The version specifies the size of the QR code:// a QR code with version v has 4v+17 pixels on a side.// Versions number from 1 to 40: the larger the version,// the more information the code can store.typeVersionintconstMinVersion = 1constMaxVersion = 40func ( Version) () string {returnstrconv.Itoa(int())}func ( Version) () int {if <= 9 {return0 }if <= 26 {return1 }return2}// DataBytes returns the number of data bytes that can be// stored in a QR code with the given version and level.func ( Version) ( Level) int { := &vtab[] := &.level[]return .bytes - .nblock*.check}// Encoding implements a QR data encoding scheme.// The implementations--Numeric, Alphanumeric, and String--specify// the character set and the mapping from UTF-8 to code bits.// The more restrictive the mode, the fewer code bits are needed.typeEncodinginterface {Check() errorBits(v Version) intEncode(b *Bits, v Version)}typeBitsstruct {b []bytenbitint}func ( *Bits) () { .b = .b[:0] .nbit = 0}func ( *Bits) () int {return .nbit}func ( *Bits) () []byte {if .nbit%8 != 0 {panic("fractional byte") }return .b}func ( *Bits) ( []byte) {if .nbit%8 != 0 {panic("fractional byte") } .b = append(.b, ...) .nbit += 8 * len()}func ( *Bits) ( uint, int) {for > 0 { := if > 8 { = 8 }if .nbit%8 == 0 { .b = append(.b, 0) } else { := -.nbit & 7if > { = } } .nbit += := uint( - ) .b[len(.b)-1] |= uint8( >> << uint(-.nbit&7)) -= >> << -= }}// Num is the encoding for numeric data.// The only valid characters are the decimal digits 0 through 9.typeNumstringfunc ( Num) () string {returnfmt.Sprintf("Num(%#q)", string())}func ( Num) () error {for , := range {if < '0' || '9' < {returnfmt.Errorf("non-numeric string %#q", string()) } }returnnil}varnumLen = [3]int{10, 12, 14}func ( Num) ( Version) int {return4 + numLen[.sizeClass()] + (10*len()+2)/3}func ( Num) ( *Bits, Version) { .Write(1, 4) .Write(uint(len()), numLen[.sizeClass()])varintfor = 0; +3 <= len(); += 3 { := uint([]-'0')*100 + uint([+1]-'0')*10 + uint([+2]-'0') .Write(, 10) }switchlen() - {case1: := uint([] - '0') .Write(, 4)case2: := uint([]-'0')*10 + uint([+1]-'0') .Write(, 7) }}// Alpha is the encoding for alphanumeric data.// The valid characters are 0-9A-Z$%*+-./: and space.typeAlphastringconstalphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"func ( Alpha) () string {returnfmt.Sprintf("Alpha(%#q)", string())}func ( Alpha) () error {for , := range {ifstrings.IndexRune(alphabet, ) < 0 {returnfmt.Errorf("non-alphanumeric string %#q", string()) } }returnnil}varalphaLen = [3]int{9, 11, 13}func ( Alpha) ( Version) int {return4 + alphaLen[.sizeClass()] + (11*len()+1)/2}func ( Alpha) ( *Bits, Version) { .Write(2, 4) .Write(uint(len()), alphaLen[.sizeClass()])varintfor = 0; +2 <= len(); += 2 { := uint(strings.IndexRune(alphabet, rune([])))*45 +uint(strings.IndexRune(alphabet, rune([+1]))) .Write(, 11) }if < len() { := uint(strings.IndexRune(alphabet, rune([]))) .Write(, 6) }}// String is the encoding for 8-bit data. All bytes are valid.typeStringstringfunc ( String) () string {returnfmt.Sprintf("String(%#q)", string())}func ( String) () error {returnnil}varstringLen = [3]int{8, 16, 16}func ( String) ( Version) int {return4 + stringLen[.sizeClass()] + 8*len()}func ( String) ( *Bits, Version) { .Write(4, 4) .Write(uint(len()), stringLen[.sizeClass()])for := 0; < len(); ++ { .Write(uint([]), 8) }}// A Pixel describes a single pixel in a QR code.typePixeluint32const (BlackPixel = 1 << iotaInvert)func ( Pixel) () uint {returnuint( >> 6)}func ( uint) Pixel {returnPixel( << 6)}func ( PixelRole) () Pixel {returnPixel( << 2)}func ( Pixel) () PixelRole {returnPixelRole(>>2) & 15}func ( Pixel) () string { := .Role().String()if &Black != 0 { += "+black" }if &Invert != 0 { += "+invert" } += "+" + strconv.FormatUint(uint64(.Offset()), 10)return}// A PixelRole describes the role of a QR pixel.typePixelRoleuint32const ( _ PixelRole = iotaPosition// position squares (large)Alignment// alignment squares (small)Timing// timing strip between position squaresFormat// format metadataPVersion// version patternUnused// unused pixelData// data bitCheck// error correction check bitExtra)varroles = []string{"","position","alignment","timing","format","pversion","unused","data","check","extra",}func ( PixelRole) () string {ifPosition <= && <= Check {returnroles[] }returnstrconv.Itoa(int())}// A Level represents a QR error correction level.// From least to most tolerant of errors, they are L, M, Q, H.typeLevelintconst (LLevel = iotaMQH)func ( Level) () string {ifL <= && <= H {return"LMQH"[ : +1] }returnstrconv.Itoa(int())}// A Code is a square pixel grid.typeCodestruct {Bitmap []byte// 1 is black, 0 is whiteSizeint// number of pixels on a sideStrideint// number of bytes per row}func ( *Code) (, int) bool {return0 <= && < .Size && 0 <= && < .Size && .Bitmap[*.Stride+/8]&(1<<uint(7-&7)) != 0}// A Mask describes a mask that is applied to the QR// code to avoid QR artifacts being interpreted as// alignment and timing patterns (such as the squares// in the corners). Valid masks are integers from 0 to 7.typeMaskint// http://www.swetake.com/qr/qr5_en.htmlvarmfunc = []func(int, int) bool{func(, int) bool { return (+)%2 == 0 },func(, int) bool { return %2 == 0 },func(, int) bool { return %3 == 0 },func(, int) bool { return (+)%3 == 0 },func(, int) bool { return (/2+/3)%2 == 0 },func(, int) bool { return *%2+*%3 == 0 },func(, int) bool { return (*%2+*%3)%2 == 0 },func(, int) bool { return (*%3+(+)%2)%2 == 0 },}func ( Mask) (, int) bool {if < 0 {returnfalse }returnmfunc[](, )}// A Plan describes how to construct a QR code// with a specific version, level, and mask.typePlanstruct {VersionVersionLevelLevelMaskMaskDataBytesint// number of data bytesCheckBytesint// number of error correcting (checksum) bytesBlocksint// number of data blocksPixel [][]Pixel// pixel map}// NewPlan returns a Plan for a QR code with the given// version, level, and mask.func ( Version, Level, Mask) (*Plan, error) { , := vplan()if != nil {returnnil, }if := fplan(, , ); != nil {returnnil, }if := lplan(, , ); != nil {returnnil, }if := mplan(, ); != nil {returnnil, }return , nil}func ( *Bits) ( int) {if < 0 {panic("qr: invalid pad size") }if <= 4 { .Write(0, ) } else { .Write(0, 4) -= 4 -= -.Bits() & 7 .Write(0, -.Bits()&7) := / 8for := 0; < ; += 2 { .Write(0xec, 8)if +1 >= {break } .Write(0x11, 8) } }}func ( *Bits) ( Version, Level) { := .DataBytes()if .nbit < *8 { .Pad(*8 - .nbit) }if .nbit != *8 {panic("qr: too much data") } := .Bytes() := &vtab[] := &.level[] := / .nblock := % .nblock := make([]byte, .check) := gf256.NewRSEncoder(Field, .check)for := 0; < .nblock; ++ {if == .nblock- { ++ } .ECC([:], ) .Append() = [:] }iflen(.Bytes()) != .bytes {panic("qr: internal error") }}func ( *Plan) ( ...Encoding) (*Code, error) {varBitsfor , := range {if := .Check(); != nil {returnnil, } .Encode(&, .Version) }if .Bits() > .DataBytes*8 {returnnil, fmt.Errorf("cannot encode %d bits into %d-bit code", .Bits(), .DataBytes*8) } .AddCheckBytes(.Version, .Level) := .Bytes()// Now we have the checksum bytes and the data bytes. // Construct the actual code. := &Code{Size: len(.Pixel), Stride: (len(.Pixel) + 7) &^ 7} .Bitmap = make([]byte, .Stride*.Size) := .Bitmapfor , := range .Pixel {for , := range {switch .Role() {caseData, Check: := .Offset()if [/8]&(1<<uint(7-&7)) != 0 { ^= Black } }if &Black != 0 { [/8] |= 1 << uint(7-&7) } } = [.Stride:] }return , nil}// A version describes metadata associated with a version.typeversionstruct {aposintastrideintbytesintpatternintlevel [4]level}typelevelstruct {nblockintcheckint}varvtab = []version{ {}, {100, 100, 26, 0x0, [4]level{{1, 7}, {1, 10}, {1, 13}, {1, 17}}}, // 1 {16, 100, 44, 0x0, [4]level{{1, 10}, {1, 16}, {1, 22}, {1, 28}}}, // 2 {20, 100, 70, 0x0, [4]level{{1, 15}, {1, 26}, {2, 18}, {2, 22}}}, // 3 {24, 100, 100, 0x0, [4]level{{1, 20}, {2, 18}, {2, 26}, {4, 16}}}, // 4 {28, 100, 134, 0x0, [4]level{{1, 26}, {2, 24}, {4, 18}, {4, 22}}}, // 5 {32, 100, 172, 0x0, [4]level{{2, 18}, {4, 16}, {4, 24}, {4, 28}}}, // 6 {20, 16, 196, 0x7c94, [4]level{{2, 20}, {4, 18}, {6, 18}, {5, 26}}}, // 7 {22, 18, 242, 0x85bc, [4]level{{2, 24}, {4, 22}, {6, 22}, {6, 26}}}, // 8 {24, 20, 292, 0x9a99, [4]level{{2, 30}, {5, 22}, {8, 20}, {8, 24}}}, // 9 {26, 22, 346, 0xa4d3, [4]level{{4, 18}, {5, 26}, {8, 24}, {8, 28}}}, // 10 {28, 24, 404, 0xbbf6, [4]level{{4, 20}, {5, 30}, {8, 28}, {11, 24}}}, // 11 {30, 26, 466, 0xc762, [4]level{{4, 24}, {8, 22}, {10, 26}, {11, 28}}}, // 12 {32, 28, 532, 0xd847, [4]level{{4, 26}, {9, 22}, {12, 24}, {16, 22}}}, // 13 {24, 20, 581, 0xe60d, [4]level{{4, 30}, {9, 24}, {16, 20}, {16, 24}}}, // 14 {24, 22, 655, 0xf928, [4]level{{6, 22}, {10, 24}, {12, 30}, {18, 24}}}, // 15 {24, 24, 733, 0x10b78, [4]level{{6, 24}, {10, 28}, {17, 24}, {16, 30}}}, // 16 {28, 24, 815, 0x1145d, [4]level{{6, 28}, {11, 28}, {16, 28}, {19, 28}}}, // 17 {28, 26, 901, 0x12a17, [4]level{{6, 30}, {13, 26}, {18, 28}, {21, 28}}}, // 18 {28, 28, 991, 0x13532, [4]level{{7, 28}, {14, 26}, {21, 26}, {25, 26}}}, // 19 {32, 28, 1085, 0x149a6, [4]level{{8, 28}, {16, 26}, {20, 30}, {25, 28}}}, // 20 {26, 22, 1156, 0x15683, [4]level{{8, 28}, {17, 26}, {23, 28}, {25, 30}}}, // 21 {24, 24, 1258, 0x168c9, [4]level{{9, 28}, {17, 28}, {23, 30}, {34, 24}}}, // 22 {28, 24, 1364, 0x177ec, [4]level{{9, 30}, {18, 28}, {25, 30}, {30, 30}}}, // 23 {26, 26, 1474, 0x18ec4, [4]level{{10, 30}, {20, 28}, {27, 30}, {32, 30}}}, // 24 {30, 26, 1588, 0x191e1, [4]level{{12, 26}, {21, 28}, {29, 30}, {35, 30}}}, // 25 {28, 28, 1706, 0x1afab, [4]level{{12, 28}, {23, 28}, {34, 28}, {37, 30}}}, // 26 {32, 28, 1828, 0x1b08e, [4]level{{12, 30}, {25, 28}, {34, 30}, {40, 30}}}, // 27 {24, 24, 1921, 0x1cc1a, [4]level{{13, 30}, {26, 28}, {35, 30}, {42, 30}}}, // 28 {28, 24, 2051, 0x1d33f, [4]level{{14, 30}, {28, 28}, {38, 30}, {45, 30}}}, // 29 {24, 26, 2185, 0x1ed75, [4]level{{15, 30}, {29, 28}, {40, 30}, {48, 30}}}, // 30 {28, 26, 2323, 0x1f250, [4]level{{16, 30}, {31, 28}, {43, 30}, {51, 30}}}, // 31 {32, 26, 2465, 0x209d5, [4]level{{17, 30}, {33, 28}, {45, 30}, {54, 30}}}, // 32 {28, 28, 2611, 0x216f0, [4]level{{18, 30}, {35, 28}, {48, 30}, {57, 30}}}, // 33 {32, 28, 2761, 0x228ba, [4]level{{19, 30}, {37, 28}, {51, 30}, {60, 30}}}, // 34 {28, 24, 2876, 0x2379f, [4]level{{19, 30}, {38, 28}, {53, 30}, {63, 30}}}, // 35 {22, 26, 3034, 0x24b0b, [4]level{{20, 30}, {40, 28}, {56, 30}, {66, 30}}}, // 36 {26, 26, 3196, 0x2542e, [4]level{{21, 30}, {43, 28}, {59, 30}, {70, 30}}}, // 37 {30, 26, 3362, 0x26a64, [4]level{{22, 30}, {45, 28}, {62, 30}, {74, 30}}}, // 38 {24, 28, 3532, 0x27541, [4]level{{24, 30}, {47, 28}, {65, 30}, {77, 30}}}, // 39 {28, 28, 3706, 0x28c69, [4]level{{25, 30}, {49, 28}, {68, 30}, {81, 30}}}, // 40}func ( int) [][]Pixel { := make([][]Pixel, ) := make([]Pixel, *)for := range { [], = [:], [:] }return}// vplan creates a Plan for the given version.func ( Version) (*Plan, error) { := &Plan{Version: }if < 1 || > 40 {returnnil, fmt.Errorf("invalid QR version %d", int()) } := 17 + int()*4 := grid() .Pixel = // Timing markers (overwritten by boxes).const = 6// timing is in row/column 6 (counting from 0)for := range { := Timing.Pixel()if &1 == 0 { |= Black } [][] = [][] = }// Position boxes.posBox(, 0, 0)posBox(, -7, 0)posBox(, 0, -7)// Alignment boxes. := &vtab[]for := 4; +5 < ; {for := 4; +5 < ; {// don't overwrite timing markersif ( < 7 && < 7) || ( < 7 && +5 >= -7) || (+5 >= -7 && < 7) { } else {alignBox(, , ) }if == 4 { = .apos } else { += .astride } }if == 4 { = .apos } else { += .astride } }// Version pattern. := vtab[].patternif != 0 { := for := 0; < 6; ++ {for := 0; < 3; ++ { := PVersion.Pixel()if &1 != 0 { |= Black } [-11+][] = [][-11+] = >>= 1 } } }// One lonely black pixel [-8][8] = Unused.Pixel() | Blackreturn , nil}// fplan adds the format pixelsfunc ( Level, Mask, *Plan) error {// Format pixels. := uint32(^1) << 13// level: L=01, M=00, Q=11, H=10 |= uint32() << 10// maskconst = 0x537 := for := 14; >= 10; -- {if &(1<<uint()) != 0 { ^= << uint(-10) } } |= := uint32(0x5412) := len(.Pixel)for := uint(0); < 15; ++ { := Format.Pixel() + OffsetPixel()if (>>)&1 == 1 { |= Black }if (>>)&1 == 1 { ^= Invert | Black }// top leftswitch {case < 6: .Pixel[][8] = case < 8: .Pixel[+1][8] = case < 9: .Pixel[8][7] = default: .Pixel[8][14-] = }// bottom rightswitch {case < 8: .Pixel[8][-1-int()] = default: .Pixel[-1-int(14-)][8] = } }returnnil}// lplan edits a version-only Plan to add information// about the error correction levels.func ( Version, Level, *Plan) error { .Level = := vtab[].level[].nblock := vtab[].level[].check := (vtab[].bytes - *) / := (vtab[].bytes - *) % := (* + ) * 8 := * * 8 .DataBytes = vtab[].bytes - * .CheckBytes = * .Blocks = // Make data + checksum pixels. := make([]Pixel, )for := range { [] = Data.Pixel() | OffsetPixel(uint()) } := make([]Pixel, )for := range { [] = Check.Pixel() | OffsetPixel(uint(+)) }// Split into blocks. := make([][]Pixel, ) := make([][]Pixel, )for := 0; < ; ++ {// The last few blocks have an extra data byte (8 pixels). := if >= - { ++ } [], = [0:*8], [*8:] [], = [0:*8], [*8:] }iflen() != 0 || len() != 0 {panic("data/check math") }// Build up bit sequence, taking first byte of each block, // then second byte, and so on. Then checksums. := make([]Pixel, +) := for := 0; < +1; ++ {for , := range {if *8 < len() {copy(, [*8:(+1)*8]) = [8:] } } }for := 0; < ; ++ {for , := range {if *8 < len() {copy(, [*8:(+1)*8]) = [8:] } } }iflen() != 0 {panic("dst math") }// Sweep up pair of columns, // then down, assigning to right then left pixel. // Repeat. // See Figure 2 of http://www.pclviewer.com/rs2/qrtopology.htm := len(.Pixel) := make([]Pixel, 7)for := range { [] = Extra.Pixel() } := append(, ...)for := ; > 0; {for := - 1; >= 0; -- {if .Pixel[][-1].Role() == 0 { .Pixel[][-1], = [0], [1:] }if .Pixel[][-2].Role() == 0 { .Pixel[][-2], = [0], [1:] } } -= 2if == 7 { // vertical timing strip -- }for := 0; < ; ++ {if .Pixel[][-1].Role() == 0 { .Pixel[][-1], = [0], [1:] }if .Pixel[][-2].Role() == 0 { .Pixel[][-2], = [0], [1:] } } -= 2 }returnnil}// mplan edits a version+level-only Plan to add the mask.func ( Mask, *Plan) error { .Mask = for , := range .Pixel {for , := range {if := .Role(); ( == Data || == Check || == Extra) && .Mask.Invert(, ) { [] ^= Black | Invert } } }returnnil}// posBox draws a position (large) box at upper left x, y.func ( [][]Pixel, , int) { := Position.Pixel()// boxfor := 0; < 7; ++ {for := 0; < 7; ++ { := if == 0 || == 6 || == 0 || == 6 || 2 <= && <= 4 && 2 <= && <= 4 { |= Black } [+][+] = } }// white borderfor := -1; < 8; ++ {if0 <= + && + < len() {if > 0 { [+][-1] = }if +7 < len() { [+][+7] = } } }for := -1; < 8; ++ {if0 <= + && + < len() {if > 0 { [-1][+] = }if +7 < len() { [+7][+] = } } }}// alignBox draw an alignment (small) box at upper left x, y.func ( [][]Pixel, , int) {// box := Alignment.Pixel()for := 0; < 5; ++ {for := 0; < 5; ++ { := if == 0 || == 4 || == 0 || == 4 || == 2 && == 2 { |= Black } [+][+] = } }}
The pages are generated with Goldsv0.6.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.