package goqr import ( "math" ) const maxPoly = 64 type galoisField struct { p int log []uint8 exp []uint8 } var gf16Exp = []uint8{ 0x01, 0x02, 0x04, 0x08, 0x03, 0x06, 0x0c, 0x0b, 0x05, 0x0a, 0x07, 0x0e, 0x0f, 0x0d, 0x09, 0x01, } var gf16Log = []uint8{ 0x00, 0x0f, 0x01, 0x04, 0x02, 0x08, 0x05, 0x0a, 0x03, 0x0e, 0x09, 0x07, 0x06, 0x0d, 0x0b, 0x0c, } var gf16 = galoisField{ p: 15, log: gf16Log, exp: gf16Exp, } var gf256Exp = [256]uint8{ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26, 0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23, 0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1, 0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, 0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2, 0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce, 0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc, 0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54, 0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73, 0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff, 0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41, 0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6, 0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09, 0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16, 0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x01, } var gf256Log = [256]uint8{ 0x00, 0xff, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b, 0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71, 0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45, 0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6, 0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88, 0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40, 0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d, 0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57, 0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18, 0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e, 0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61, 0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2, 0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6, 0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a, 0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7, 0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf, } var gf256 = galoisField{ 255, gf256Log[:], gf256Exp[:], } /************************************************************************ * Polynomial operations */ func polyAdd(dst, src []uint8, c uint8, shift int, gf *galoisField) { logC := gf.log[c] if c == 0 { return } for i := 0; i < maxPoly; i++ { p := i + shift v := src[i] if p < 0 || p >= maxPoly { continue } if v == 0 { continue } pos := (int(gf.log[v]) + int(logC)) % gf.p dst[p] ^= gf.exp[pos] } } func polyEval(s []uint8, x uint8, gf *galoisField) uint8 { sum := uint8(0) logX := gf.log[x] if x == 0 { return s[0] } for i := 0; i < maxPoly; i++ { c := s[i] if c == 0 { continue } sum ^= gf.exp[(int(gf.log[c])+int(logX)*i)%gf.p] } return sum } /************************************************************************ * Berlekamp-Massey algorithm for finding error locator polynomials. */ func berlekampMassey(s []uint8, num int, gf *galoisField, sigma []uint8) { C := make([]uint8, maxPoly) B := make([]uint8, maxPoly) L := 0 m := 1 b := uint8(1) B[0] = 1 C[0] = 1 for n := 0; n < num; n++ { d := s[n] for i := 1; i <= L; i++ { if !(C[i] > 0 && s[n-i] > 0) { continue } d ^= gf.exp[(int(gf.log[C[i]])+int(gf.log[s[n-i]]))%gf.p] } mult := gf.exp[(gf.p-int(gf.log[b])+int(gf.log[d]))%gf.p] if d == 0 { m++ } else if L*2 <= n { T := make([]uint8, 0) T = append(T, C...) polyAdd(C, B, mult, m, gf) B = B[:0] B = append(B, T...) L = n + 1 - L b = d m = 1 } else { polyAdd(C, B, mult, m, gf) m++ } } sigma = sigma[:0] sigma = append(sigma, C...) } /************************************************************************ * Code stream error correction * * Generator polynomial for GF(2^8) is x^8 + x^4 + x^3 + x^2 + 1 */ func blockSyndromes(data []uint8, bs, npar int, s []uint8) int { nonzero := 0 for i := 0; i < maxPoly; i++ { s[i] = 0 } for i := 0; i < npar; i++ { for j := 0; j < bs; j++ { c := data[bs-j-1] if c == 0 { continue } s[i] ^= gf256Exp[((int)(gf256Log[c])+i*j)%255] } if s[i] != 0 { nonzero = 1 } } return nonzero } func elocPoly(omega []uint8, s []uint8, sigma []uint8, npar int) { for i := 0; i < maxPoly; i++ { omega[i] = 0 } for i := 0; i < npar; i++ { a := sigma[i] logA := gf256Log[a] if a == 0 { continue } for j := 0; j+1 < maxPoly; j++ { b := s[j+1] if i+j >= npar { break } if b == 0 { continue } omega[i+j] ^= gf256Exp[(int(logA)+int(gf256Log[b]))%255] } } } func correctBlock(data []uint8, ecc *qrRsParams) error { npar := ecc.bs - ecc.dw s := make([]uint8, maxPoly) // Compute syndrome vector if 0 == blockSyndromes(data, ecc.bs, npar, s) { return nil } sigma := make([]uint8, maxPoly) berlekampMassey(s, npar, &gf256, sigma) // Compute derivative of sigma sigmaDeriv := make([]uint8, maxPoly) for i := 0; i+1 < maxPoly; i += 2 { sigmaDeriv[i] = sigma[i+1] } // Compute error evaluator polynomial omega := make([]uint8, maxPoly) elocPoly(omega, s, sigma, npar-1) // Find error locations and magnitudes for i := 0; i < ecc.bs; i++ { xinv := gf256Exp[255-i] if 0 == polyEval(sigma, xinv, &gf256) { sdX := polyEval(sigmaDeriv, xinv, &gf256) omegaX := polyEval(omega, xinv, &gf256) error := gf256Exp[(255-int(gf256Log[sdX])+int(gf256Log[omegaX]))%255] data[ecc.bs-i-1] ^= error } } if blockSyndromes(data, ecc.bs, npar, s) != 0 { return ErrDataEcc } return nil } /************************************************************************ * Format value error correction * * Generator polynomial for GF(2^4) is x^4 + x + 1 */ const formatMaxError = 3 const formatSyndrome = formatMaxError * 2 const formatBits = 15 func formatSyndromes(u uint16, s []uint8) int { nonzero := 0 for i := 0; i < maxPoly; i++ { s[i] = 0 } for i := 0; i < formatSyndrome; i++ { s[i] = 0 for j := 0; j < formatBits; j++ { if u&(uint16(1 << uint(j))) != 0 { s[i] ^= gf16Exp[((i+1)*j)%15] } } if s[i] != 0 { nonzero = 1 } } return nonzero } func correctFormat(fRet *uint16) error { u := *fRet // Evaluate U (received codeword) at each of alpha_1 .. alpha_6 // to get S_1 .. S_6 (but we index them from 0). s := make([]uint8, maxPoly) if 0 == formatSyndromes(u, s) { return nil } sigma := make([]uint8, maxPoly) berlekampMassey(s, formatSyndrome, &gf16, sigma) // Now, find the roots of the polynomial for i := 0; i < 15; i++ { if 0 == polyEval(sigma, gf16Exp[15-i], &gf16) { u ^= 1 << uint16(i) } } if 0 != formatSyndromes(u, s) { return ErrFormatEcc } *fRet = u return nil } /************************************************************************ * Decoder algorithm */ type datastream struct { raw [qrMaxPayload]uint8 dataBits int ptr int data [qrMaxPayload]uint8 } func maskBit(mask, i, j int) int { k := 0 switch mask { case 0: k = (i + j) % 2 case 1: k = i % 2 case 2: k = j % 3 case 3: k = (i + j) % 3 case 4: k = ((i / 2) + (j / 3)) % 2 case 5: k = (i*j)%2 + (i*j)%3 case 6: k = ((i*j)%2 + (i*j)%3) % 2 case 7: k = ((i*j)%3 + (i+j)%2) % 2 default: return 0 } if k != 0 { return 0 } return 1 } func reservedCell(version, i, j int) int { ver := &qrVersionDb[version] size := version*4 + 17 ai := -1 aj := -1 a := 0 // Finder + format: top left if i < 9 && j < 9 { return 1 } // Finder + format: bottom left if i+8 >= size && j < 9 { return 1 } // Finder + format: top right if i < 9 && j+8 >= size { return 1 } // Exclude timing patterns if i == 6 || j == 6 { return 1 } // Exclude Version info, if it exists. Version info sits adjacent to // the top-right and bottom-left finders in three rows, bounded by // the timing pattern. if version >= 7 { if i < 6 && j+11 >= size { return 1 } if i+11 >= size && j < 6 { return 1 } } // Exclude alignment patterns for a = 0; a < qrMaxAliment && ver.apat[a] != 0; a++ { p := ver.apat[a] if int(math.Abs(float64(p-i))) < 3 { ai = a } if int(math.Abs(float64(p-j))) < 3 { aj = a } } if ai >= 0 && aj >= 0 { a-- if ai > 0 && ai < a { return 1 } if aj > 0 && aj < a { return 1 } if aj == a && ai == a { return 1 } } return 0 } func codestreamEcc(data *QRData, ds *datastream) error { ver := &qrVersionDb[data.Version] sbEcc := &ver.ecc[data.EccLevel] var lbEcc qrRsParams lbCount := (ver.dataBytes - sbEcc.bs*sbEcc.ns) / (sbEcc.bs + 1) bc := lbCount + sbEcc.ns eccOffset := sbEcc.dw*bc + lbCount dstOffset := 0 lbEcc = *sbEcc lbEcc.dw++ lbEcc.bs++ for i := 0; i < bc; i++ { dst := ds.data[dstOffset:] ecc := sbEcc if i < sbEcc.ns { ecc = sbEcc } else { ecc = &lbEcc } numEc := ecc.bs - ecc.dw for j := 0; j < ecc.dw; j++ { dst[j] = ds.raw[j*bc+i] } for j := 0; j < numEc; j++ { dst[ecc.dw+j] = ds.raw[eccOffset+j*bc+i] } err := correctBlock(dst, ecc) if err != nil { return err } dstOffset += ecc.dw } ds.dataBits = dstOffset * 8 return nil } func bitsRemaining(ds *datastream) int { return ds.dataBits - ds.ptr } func takeBits(ds *datastream, len int) int { ret := 0 for len > 0 && (ds.ptr < ds.dataBits) { b := ds.data[ds.ptr>>3] bitpos := ds.ptr & 7 ret <<= 1 if ((b << uint(bitpos)) & 0x80) != 0 { ret |= 1 } ds.ptr++ len-- } return ret } func numericTuple(data *QRData, ds *datastream, bits, digits int) int { if bitsRemaining(ds) < bits { return -1 } tuple := takeBits(ds, bits) for i := digits - 1; i >= 0; i-- { data.Payload = append(data.Payload, uint8(tuple%10)+uint8('0')) tuple /= 10 } return 0 } func decodeNumeric(data *QRData, ds *datastream) error { bits := 14 if data.Version < 10 { bits = 10 } else if data.Version < 27 { bits = 12 } count := takeBits(ds, bits) if len(data.Payload)+count+1 > qrMaxPayload { return ErrDataOverflow } for count >= 3 { if numericTuple(data, ds, 10, 3) < 0 { return ErrDataUnderflow } count -= 3 } if count >= 2 { if numericTuple(data, ds, 7, 2) < 0 { return ErrDataUnderflow } count -= 2 } if count > 0 { if numericTuple(data, ds, 4, 1) < 0 { return ErrDataUnderflow } } return nil } var alphaMap = []byte("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:") func alphaTuple(data *QRData, ds *datastream, bits, digits int) int { if bitsRemaining(ds) < bits { return -1 } tuple := takeBits(ds, bits) payloadLen := len(data.Payload) data.Payload = append(data.Payload, make([]uint8, digits)...) for i := 0; i < digits; i++ { data.Payload[payloadLen+digits-i-1] = alphaMap[tuple%45] tuple /= 45 } return 0 } func decodeAlpha(data *QRData, ds *datastream) error { bits := 13 if data.Version < 10 { bits = 9 } else if data.Version < 27 { bits = 11 } count := takeBits(ds, bits) if len(data.Payload)+count+1 > qrMaxPayload { return ErrDataOverflow } for count >= 2 { if alphaTuple(data, ds, 11, 2) < 0 { return ErrDataUnderflow } count -= 2 } if count > 0 { if alphaTuple(data, ds, 6, 1) < 0 { return ErrDataUnderflow } } return nil } func decodeByte(data *QRData, ds *datastream) error { bits := 16 if data.Version < 10 { bits = 8 } count := takeBits(ds, bits) if len(data.Payload)+count+1 > qrMaxPayload { return ErrDataOverflow } if bitsRemaining(ds) < count*8 { return ErrDataUnderflow } for i := 0; i < count; i++ { data.Payload = append(data.Payload, uint8(takeBits(ds, 8))) } return nil } func decodeKanji(data *QRData, ds *datastream) error { bits := 12 if data.Version < 10 { bits = 8 } else if data.Version < 27 { bits = 10 } count := takeBits(ds, bits) if len(data.Payload)+count*2+1 > qrMaxPayload { return ErrDataOverflow } if bitsRemaining(ds) < count*13 { return ErrDataUnderflow } for i := 0; i < count; i++ { d := takeBits(ds, 13) msB := d / 0xc0 lsB := d % 0xc0 intermediate := uint16((msB << 8) | lsB) var sjw uint16 if intermediate+0x8140 <= 0x9ffc { // bytes are in the range 0x8140 to 0x9FFC sjw = intermediate + 0x8140 } else { // bytes are in the range 0xE040 to 0xEBBF sjw = intermediate + 0xc140 } data.Payload = append(data.Payload, uint8(sjw>>8)) data.Payload = append(data.Payload, uint8(sjw&0xff)) } return nil } func decodeEci(data *QRData, ds *datastream) error { if bitsRemaining(ds) < 8 { return ErrDataOverflow } data.Eci = uint32(takeBits(ds, 8)) if (data.Eci & 0xc0) == 0x80 { if bitsRemaining(ds) < 8 { return ErrDataUnderflow } data.Eci = (data.Eci << 8) | uint32(takeBits(ds, 8)) } else if (data.Eci & 0xe0) == 0xc0 { if bitsRemaining(ds) < 16 { return ErrDataUnderflow } data.Eci = (data.Eci << 16) | uint32(takeBits(ds, 16)) } return nil } func decodePayload(data *QRData, ds *datastream) error { for bitsRemaining(ds) >= 4 { var err error _type := takeBits(ds, 4) switch _type { case qrDataTypeNumeric: err = decodeNumeric(data, ds) case qrDataTypeAlpha: err = decodeAlpha(data, ds) case qrDataTypeByte: err = decodeByte(data, ds) case qrDataTypeKanji: err = decodeKanji(data, ds) case 7: err = decodeEci(data, ds) default: goto done } if err != nil { return err } if 0 == (_type&(_type-1)) && (_type > data.DataType) { data.DataType = _type } } done: return nil }