pax_global_header00006660000000000000000000000064134327205050014513gustar00rootroot0000000000000052 comment=6c824513baccd76c674ce72112c29ef550187b08 barcode-1.0.1/000077500000000000000000000000001343272050500131115ustar00rootroot00000000000000barcode-1.0.1/.gitignore000066400000000000000000000000111343272050500150710ustar00rootroot00000000000000.vscode/ barcode-1.0.1/LICENSE000066400000000000000000000020751343272050500141220ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2014 Florian Sundermann Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. barcode-1.0.1/README.md000066400000000000000000000022161343272050500143710ustar00rootroot00000000000000[![Join the chat at https://gitter.im/golang-barcode/Lobby](https://badges.gitter.im/golang-barcode/Lobby.svg)](https://gitter.im/golang-barcode/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ## Introduction ## This is a package for GO which can be used to create different types of barcodes. ## Supported Barcode Types ## * 2 of 5 * Aztec Code * Codabar * Code 128 * Code 39 * Code 93 * Datamatrix * EAN 13 * EAN 8 * PDF 417 * QR Code ## Example ## This is a simple example on how to create a QR-Code and write it to a png-file ```go package main import ( "image/png" "os" "github.com/boombuler/barcode" "github.com/boombuler/barcode/qr" ) func main() { // Create the barcode qrCode, _ := qr.Encode("Hello World", qr.M, qr.Auto) // Scale the barcode to 200x200 pixels qrCode, _ = barcode.Scale(qrCode, 200, 200) // create the output file file, _ := os.Create("qrcode.png") defer file.Close() // encode the barcode as png png.Encode(file, qrCode) } ``` ## Documentation ## See [GoDoc](https://godoc.org/github.com/boombuler/barcode) To create a barcode use the Encode function from one of the subpackages. barcode-1.0.1/aztec/000077500000000000000000000000001343272050500142175ustar00rootroot00000000000000barcode-1.0.1/aztec/aztec_test.go000066400000000000000000000131571343272050500167220ustar00rootroot00000000000000package aztec import ( "testing" ) func encodeTest(t *testing.T, data, wanted string) { result, err := Encode([]byte(data), DEFAULT_EC_PERCENT, DEFAULT_LAYERS) if err != nil { t.Error(err) } else { ac, ok := result.(*aztecCode) if !ok { t.Error("returned barcode is no aztec code...") } else if draw := ac.string(); draw != wanted { t.Errorf("Invalid Barcode returned:\n%s", draw) } } } func Test_Encode1(t *testing.T) { encodeTest(t, "This is an example Aztec symbol for Wikipedia.", "X X X X X X X X \n"+ "X X X X X X X X X X \n"+ "X X X X X X X X X X X \n"+ "X X X X X X X X X X X \n"+ " X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X \n"+ "X X X X X X X X X X \n"+ " X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X \n"+ " X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X \n"+ " X X X \n"+ " X X X X X X X X X X \n"+ " X X X X X X X X X X \n") } func Test_Encode2(t *testing.T) { encodeTest(t, "Aztec Code is a public domain 2D matrix barcode symbology"+ " of nominally square symbols built on a square grid with a "+ "distinctive square bullseye pattern at their center.", " X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X X X X X X X X X \n"+ " X X X X X X X X X X X X X X X X \n"+ "X X X X X X X X X X X X X \n") } barcode-1.0.1/aztec/azteccode.go000066400000000000000000000021301343272050500165030ustar00rootroot00000000000000package aztec import ( "bytes" "image" "image/color" "github.com/boombuler/barcode" "github.com/boombuler/barcode/utils" ) type aztecCode struct { *utils.BitList size int content []byte } func newAztecCode(size int) *aztecCode { return &aztecCode{utils.NewBitList(size * size), size, nil} } func (c *aztecCode) Content() string { return string(c.content) } func (c *aztecCode) Metadata() barcode.Metadata { return barcode.Metadata{barcode.TypeAztec, 2} } func (c *aztecCode) ColorModel() color.Model { return color.Gray16Model } func (c *aztecCode) Bounds() image.Rectangle { return image.Rect(0, 0, c.size, c.size) } func (c *aztecCode) At(x, y int) color.Color { if c.GetBit(x*c.size + y) { return color.Black } return color.White } func (c *aztecCode) set(x, y int) { c.SetBit(x*c.size+y, true) } func (c *aztecCode) string() string { buf := new(bytes.Buffer) for y := 0; y < c.size; y++ { for x := 0; x < c.size; x++ { if c.GetBit(x*c.size + y) { buf.WriteString("X ") } else { buf.WriteString(" ") } } buf.WriteRune('\n') } return buf.String() } barcode-1.0.1/aztec/encoder.go000066400000000000000000000164301343272050500161710ustar00rootroot00000000000000// Package aztec can create Aztec Code barcodes package aztec import ( "fmt" "github.com/boombuler/barcode" "github.com/boombuler/barcode/utils" ) const ( DEFAULT_EC_PERCENT = 33 DEFAULT_LAYERS = 0 max_nb_bits = 32 max_nb_bits_compact = 4 ) var ( word_size = []int{ 4, 6, 6, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, } ) func totalBitsInLayer(layers int, compact bool) int { tmp := 112 if compact { tmp = 88 } return (tmp + 16*layers) * layers } func stuffBits(bits *utils.BitList, wordSize int) *utils.BitList { out := new(utils.BitList) n := bits.Len() mask := (1 << uint(wordSize)) - 2 for i := 0; i < n; i += wordSize { word := 0 for j := 0; j < wordSize; j++ { if i+j >= n || bits.GetBit(i+j) { word |= 1 << uint(wordSize-1-j) } } if (word & mask) == mask { out.AddBits(word&mask, byte(wordSize)) i-- } else if (word & mask) == 0 { out.AddBits(word|1, byte(wordSize)) i-- } else { out.AddBits(word, byte(wordSize)) } } return out } func generateModeMessage(compact bool, layers, messageSizeInWords int) *utils.BitList { modeMessage := new(utils.BitList) if compact { modeMessage.AddBits(layers-1, 2) modeMessage.AddBits(messageSizeInWords-1, 6) modeMessage = generateCheckWords(modeMessage, 28, 4) } else { modeMessage.AddBits(layers-1, 5) modeMessage.AddBits(messageSizeInWords-1, 11) modeMessage = generateCheckWords(modeMessage, 40, 4) } return modeMessage } func drawModeMessage(matrix *aztecCode, compact bool, matrixSize int, modeMessage *utils.BitList) { center := matrixSize / 2 if compact { for i := 0; i < 7; i++ { offset := center - 3 + i if modeMessage.GetBit(i) { matrix.set(offset, center-5) } if modeMessage.GetBit(i + 7) { matrix.set(center+5, offset) } if modeMessage.GetBit(20 - i) { matrix.set(offset, center+5) } if modeMessage.GetBit(27 - i) { matrix.set(center-5, offset) } } } else { for i := 0; i < 10; i++ { offset := center - 5 + i + i/5 if modeMessage.GetBit(i) { matrix.set(offset, center-7) } if modeMessage.GetBit(i + 10) { matrix.set(center+7, offset) } if modeMessage.GetBit(29 - i) { matrix.set(offset, center+7) } if modeMessage.GetBit(39 - i) { matrix.set(center-7, offset) } } } } func drawBullsEye(matrix *aztecCode, center, size int) { for i := 0; i < size; i += 2 { for j := center - i; j <= center+i; j++ { matrix.set(j, center-i) matrix.set(j, center+i) matrix.set(center-i, j) matrix.set(center+i, j) } } matrix.set(center-size, center-size) matrix.set(center-size+1, center-size) matrix.set(center-size, center-size+1) matrix.set(center+size, center-size) matrix.set(center+size, center-size+1) matrix.set(center+size, center+size-1) } // Encode returns an aztec barcode with the given content func Encode(data []byte, minECCPercent int, userSpecifiedLayers int) (barcode.Barcode, error) { bits := highlevelEncode(data) eccBits := ((bits.Len() * minECCPercent) / 100) + 11 totalSizeBits := bits.Len() + eccBits var layers, TotalBitsInLayer, wordSize int var compact bool var stuffedBits *utils.BitList if userSpecifiedLayers != DEFAULT_LAYERS { compact = userSpecifiedLayers < 0 if compact { layers = -userSpecifiedLayers } else { layers = userSpecifiedLayers } if (compact && layers > max_nb_bits_compact) || (!compact && layers > max_nb_bits) { return nil, fmt.Errorf("Illegal value %d for layers", userSpecifiedLayers) } TotalBitsInLayer = totalBitsInLayer(layers, compact) wordSize = word_size[layers] usableBitsInLayers := TotalBitsInLayer - (TotalBitsInLayer % wordSize) stuffedBits = stuffBits(bits, wordSize) if stuffedBits.Len()+eccBits > usableBitsInLayers { return nil, fmt.Errorf("Data to large for user specified layer") } if compact && stuffedBits.Len() > wordSize*64 { return nil, fmt.Errorf("Data to large for user specified layer") } } else { wordSize = 0 stuffedBits = nil // We look at the possible table sizes in the order Compact1, Compact2, Compact3, // Compact4, Normal4,... Normal(i) for i < 4 isn't typically used since Compact(i+1) // is the same size, but has more data. for i := 0; ; i++ { if i > max_nb_bits { return nil, fmt.Errorf("Data too large for an aztec code") } compact = i <= 3 layers = i if compact { layers = i + 1 } TotalBitsInLayer = totalBitsInLayer(layers, compact) if totalSizeBits > TotalBitsInLayer { continue } // [Re]stuff the bits if this is the first opportunity, or if the // wordSize has changed if wordSize != word_size[layers] { wordSize = word_size[layers] stuffedBits = stuffBits(bits, wordSize) } usableBitsInLayers := TotalBitsInLayer - (TotalBitsInLayer % wordSize) if compact && stuffedBits.Len() > wordSize*64 { // Compact format only allows 64 data words, though C4 can hold more words than that continue } if stuffedBits.Len()+eccBits <= usableBitsInLayers { break } } } messageBits := generateCheckWords(stuffedBits, TotalBitsInLayer, wordSize) messageSizeInWords := stuffedBits.Len() / wordSize modeMessage := generateModeMessage(compact, layers, messageSizeInWords) // allocate symbol var baseMatrixSize int if compact { baseMatrixSize = 11 + layers*4 } else { baseMatrixSize = 14 + layers*4 } alignmentMap := make([]int, baseMatrixSize) var matrixSize int if compact { // no alignment marks in compact mode, alignmentMap is a no-op matrixSize = baseMatrixSize for i := 0; i < len(alignmentMap); i++ { alignmentMap[i] = i } } else { matrixSize = baseMatrixSize + 1 + 2*((baseMatrixSize/2-1)/15) origCenter := baseMatrixSize / 2 center := matrixSize / 2 for i := 0; i < origCenter; i++ { newOffset := i + i/15 alignmentMap[origCenter-i-1] = center - newOffset - 1 alignmentMap[origCenter+i] = center + newOffset + 1 } } code := newAztecCode(matrixSize) code.content = data // draw data bits for i, rowOffset := 0, 0; i < layers; i++ { rowSize := (layers - i) * 4 if compact { rowSize += 9 } else { rowSize += 12 } for j := 0; j < rowSize; j++ { columnOffset := j * 2 for k := 0; k < 2; k++ { if messageBits.GetBit(rowOffset + columnOffset + k) { code.set(alignmentMap[i*2+k], alignmentMap[i*2+j]) } if messageBits.GetBit(rowOffset + rowSize*2 + columnOffset + k) { code.set(alignmentMap[i*2+j], alignmentMap[baseMatrixSize-1-i*2-k]) } if messageBits.GetBit(rowOffset + rowSize*4 + columnOffset + k) { code.set(alignmentMap[baseMatrixSize-1-i*2-k], alignmentMap[baseMatrixSize-1-i*2-j]) } if messageBits.GetBit(rowOffset + rowSize*6 + columnOffset + k) { code.set(alignmentMap[baseMatrixSize-1-i*2-j], alignmentMap[i*2+k]) } } } rowOffset += rowSize * 8 } // draw mode message drawModeMessage(code, compact, matrixSize, modeMessage) // draw alignment marks if compact { drawBullsEye(code, matrixSize/2, 5) } else { drawBullsEye(code, matrixSize/2, 7) for i, j := 0, 0; i < baseMatrixSize/2-1; i, j = i+15, j+16 { for k := (matrixSize / 2) & 1; k < matrixSize; k += 2 { code.set(matrixSize/2-j, k) code.set(matrixSize/2+j, k) code.set(k, matrixSize/2-j) code.set(k, matrixSize/2+j) } } } return code, nil } barcode-1.0.1/aztec/encoder_test.go000066400000000000000000000036151343272050500172310ustar00rootroot00000000000000package aztec import ( "strings" "testing" "github.com/boombuler/barcode/utils" ) func Test_StuffBits(t *testing.T) { testStuffBits := func(wordSize int, bits string, expected string) { bl := new(utils.BitList) for _, r := range bits { if r == 'X' { bl.AddBit(true) } else if r == '.' { bl.AddBit(false) } } stuffed := stuffBits(bl, wordSize) expectedBits := strings.Replace(expected, " ", "", -1) result := bitStr(stuffed) if result != expectedBits { t.Errorf("stuffBits failed for %q\nGot: %q", bits, result) } } testStuffBits(5, ".X.X. X.X.X .X.X.", ".X.X. X.X.X .X.X.") testStuffBits(5, ".X.X. ..... .X.X", ".X.X. ....X ..X.X") testStuffBits(3, "XX. ... ... ..X XXX .X. ..", "XX. ..X ..X ..X ..X .XX XX. .X. ..X") testStuffBits(6, ".X.X.. ...... ..X.XX", ".X.X.. .....X. ..X.XX XXXX.") testStuffBits(6, ".X.X.. ...... ...... ..X.X.", ".X.X.. .....X .....X ....X. X.XXXX") testStuffBits(6, ".X.X.. XXXXXX ...... ..X.XX", ".X.X.. XXXXX. X..... ...X.X XXXXX.") testStuffBits(6, "...... ..XXXX X..XX. .X.... .X.X.X .....X .X.... ...X.X .....X ....XX ..X... ....X. X..XXX X.XX.X", ".....X ...XXX XX..XX ..X... ..X.X. X..... X.X... ....X. X..... X....X X..X.. .....X X.X..X XXX.XX .XXXXX") } func Test_ModeMessage(t *testing.T) { testModeMessage := func(compact bool, layers, words int, expected string) { result := bitStr(generateModeMessage(compact, layers, words)) expectedBits := strings.Replace(expected, " ", "", -1) if result != expectedBits { t.Errorf("generateModeMessage(%v, %d, %d) failed.\nGot:%s", compact, layers, words, result) } } testModeMessage(true, 2, 29, ".X .XXX.. ...X XX.. ..X .XX. .XX.X") testModeMessage(true, 4, 64, "XX XXXXXX .X.. ...X ..XX .X.. XX..") testModeMessage(false, 21, 660, "X.X.. .X.X..X..XX .XXX ..X.. .XXX. .X... ..XXX") testModeMessage(false, 32, 4096, "XXXXX XXXXXXXXXXX X.X. ..... XXX.X ..X.. X.XXX") } barcode-1.0.1/aztec/errorcorrection.go000066400000000000000000000030141343272050500177650ustar00rootroot00000000000000package aztec import ( "github.com/boombuler/barcode/utils" ) func bitsToWords(stuffedBits *utils.BitList, wordSize int, wordCount int) []int { message := make([]int, wordCount) for i := 0; i < wordCount; i++ { value := 0 for j := 0; j < wordSize; j++ { if stuffedBits.GetBit(i*wordSize + j) { value |= (1 << uint(wordSize-j-1)) } } message[i] = value } return message } func generateCheckWords(bits *utils.BitList, totalBits, wordSize int) *utils.BitList { rs := utils.NewReedSolomonEncoder(getGF(wordSize)) // bits is guaranteed to be a multiple of the wordSize, so no padding needed messageWordCount := bits.Len() / wordSize totalWordCount := totalBits / wordSize eccWordCount := totalWordCount - messageWordCount messageWords := bitsToWords(bits, wordSize, messageWordCount) eccWords := rs.Encode(messageWords, eccWordCount) startPad := totalBits % wordSize messageBits := new(utils.BitList) messageBits.AddBits(0, byte(startPad)) for _, messageWord := range messageWords { messageBits.AddBits(messageWord, byte(wordSize)) } for _, eccWord := range eccWords { messageBits.AddBits(eccWord, byte(wordSize)) } return messageBits } func getGF(wordSize int) *utils.GaloisField { switch wordSize { case 4: return utils.NewGaloisField(0x13, 16, 1) case 6: return utils.NewGaloisField(0x43, 64, 1) case 8: return utils.NewGaloisField(0x012D, 256, 1) case 10: return utils.NewGaloisField(0x409, 1024, 1) case 12: return utils.NewGaloisField(0x1069, 4096, 1) default: return nil } } barcode-1.0.1/aztec/highlevel.go000066400000000000000000000126011343272050500165150ustar00rootroot00000000000000package aztec import ( "github.com/boombuler/barcode/utils" ) func highlevelEncode(data []byte) *utils.BitList { states := stateSlice{initialState} for index := 0; index < len(data); index++ { pairCode := 0 nextChar := byte(0) if index+1 < len(data) { nextChar = data[index+1] } switch cur := data[index]; { case cur == '\r' && nextChar == '\n': pairCode = 2 case cur == '.' && nextChar == ' ': pairCode = 3 case cur == ',' && nextChar == ' ': pairCode = 4 case cur == ':' && nextChar == ' ': pairCode = 5 } if pairCode > 0 { // We have one of the four special PUNCT pairs. Treat them specially. // Get a new set of states for the two new characters. states = updateStateListForPair(states, data, index, pairCode) index++ } else { // Get a new set of states for the new character. states = updateStateListForChar(states, data, index) } } minBitCnt := int((^uint(0)) >> 1) var result *state = nil for _, s := range states { if s.bitCount < minBitCnt { minBitCnt = s.bitCount result = s } } if result != nil { return result.toBitList(data) } else { return new(utils.BitList) } } func simplifyStates(states stateSlice) stateSlice { var result stateSlice = nil for _, newState := range states { add := true var newResult stateSlice = nil for _, oldState := range result { if add && oldState.isBetterThanOrEqualTo(newState) { add = false } if !(add && newState.isBetterThanOrEqualTo(oldState)) { newResult = append(newResult, oldState) } } if add { result = append(newResult, newState) } else { result = newResult } } return result } // We update a set of states for a new character by updating each state // for the new character, merging the results, and then removing the // non-optimal states. func updateStateListForChar(states stateSlice, data []byte, index int) stateSlice { var result stateSlice = nil for _, s := range states { if r := updateStateForChar(s, data, index); len(r) > 0 { result = append(result, r...) } } return simplifyStates(result) } // Return a set of states that represent the possible ways of updating this // state for the next character. The resulting set of states are added to // the "result" list. func updateStateForChar(s *state, data []byte, index int) stateSlice { var result stateSlice = nil ch := data[index] charInCurrentTable := charMap[s.mode][ch] > 0 var stateNoBinary *state = nil for mode := mode_upper; mode <= mode_punct; mode++ { charInMode := charMap[mode][ch] if charInMode > 0 { if stateNoBinary == nil { // Only create stateNoBinary the first time it's required. stateNoBinary = s.endBinaryShift(index) } // Try generating the character by latching to its mode if !charInCurrentTable || mode == s.mode || mode == mode_digit { // If the character is in the current table, we don't want to latch to // any other mode except possibly digit (which uses only 4 bits). Any // other latch would be equally successful *after* this character, and // so wouldn't save any bits. res := stateNoBinary.latchAndAppend(mode, charInMode) result = append(result, res) } // Try generating the character by switching to its mode. if _, ok := shiftTable[s.mode][mode]; !charInCurrentTable && ok { // It never makes sense to temporarily shift to another mode if the // character exists in the current mode. That can never save bits. res := stateNoBinary.shiftAndAppend(mode, charInMode) result = append(result, res) } } } if s.bShiftByteCount > 0 || charMap[s.mode][ch] == 0 { // It's never worthwhile to go into binary shift mode if you're not already // in binary shift mode, and the character exists in your current mode. // That can never save bits over just outputting the char in the current mode. res := s.addBinaryShiftChar(index) result = append(result, res) } return result } // We update a set of states for a new character by updating each state // for the new character, merging the results, and then removing the // non-optimal states. func updateStateListForPair(states stateSlice, data []byte, index int, pairCode int) stateSlice { var result stateSlice = nil for _, s := range states { if r := updateStateForPair(s, data, index, pairCode); len(r) > 0 { result = append(result, r...) } } return simplifyStates(result) } func updateStateForPair(s *state, data []byte, index int, pairCode int) stateSlice { var result stateSlice stateNoBinary := s.endBinaryShift(index) // Possibility 1. Latch to MODE_PUNCT, and then append this code result = append(result, stateNoBinary.latchAndAppend(mode_punct, pairCode)) if s.mode != mode_punct { // Possibility 2. Shift to MODE_PUNCT, and then append this code. // Every state except MODE_PUNCT (handled above) can shift result = append(result, stateNoBinary.shiftAndAppend(mode_punct, pairCode)) } if pairCode == 3 || pairCode == 4 { // both characters are in DIGITS. Sometimes better to just add two digits digitState := stateNoBinary. latchAndAppend(mode_digit, 16-pairCode). // period or comma in DIGIT latchAndAppend(mode_digit, 1) // space in DIGIT result = append(result, digitState) } if s.bShiftByteCount > 0 { // It only makes sense to do the characters as binary if we're already // in binary mode. result = append(result, s.addBinaryShiftChar(index).addBinaryShiftChar(index+1)) } return result } barcode-1.0.1/aztec/highlevel_test.go000066400000000000000000000115201343272050500175530ustar00rootroot00000000000000package aztec import ( "bytes" "strings" "testing" "github.com/boombuler/barcode/utils" ) func bitStr(bl *utils.BitList) string { buf := new(bytes.Buffer) for i := 0; i < bl.Len(); i++ { if bl.GetBit(i) { buf.WriteRune('X') } else { buf.WriteRune('.') } } return buf.String() } func testHighLevelEncodeString(t *testing.T, s, expectedBits string) { bits := highlevelEncode([]byte(s)) result := bitStr(bits) expectedBits = strings.Replace(expectedBits, " ", "", -1) if result != expectedBits { t.Errorf("invalid result for highlevelEncode(%q). Got:\n%s", s, result) } } func testHighLevelEncodeStringCnt(t *testing.T, s string, expectedBitCnt int) { bits := highlevelEncode([]byte(s)) if bits.Len() != expectedBitCnt { t.Errorf("invalid result for highlevelEncode(%q). Got %d, expected %d bits", s, bits.Len(), expectedBitCnt) } } func Test_HighLevelEncode(t *testing.T) { testHighLevelEncodeString(t, "A. b.", // 'A' P/S '. ' L/L b D/L '.' "...X. ..... ...XX XXX.. ...XX XXXX. XX.X") testHighLevelEncodeString(t, "Lorem ipsum.", // 'L' L/L 'o' 'r' 'e' 'm' ' ' 'i' 'p' 's' 'u' 'm' D/L '.' ".XX.X XXX.. X.... X..XX ..XX. .XXX. ....X .X.X. X...X X.X.. X.XX. .XXX. XXXX. XX.X") testHighLevelEncodeString(t, "Lo. Test 123.", // 'L' L/L 'o' P/S '. ' U/S 'T' 'e' 's' 't' D/L ' ' '1' '2' '3' '.' ".XX.X XXX.. X.... ..... ...XX XXX.. X.X.X ..XX. X.X.. X.X.X XXXX. ...X ..XX .X.. .X.X XX.X") testHighLevelEncodeString(t, "Lo...x", // 'L' L/L 'o' D/L '.' '.' '.' U/L L/L 'x' ".XX.X XXX.. X.... XXXX. XX.X XX.X XX.X XXX. XXX.. XX..X") testHighLevelEncodeString(t, ". x://abc/.", //P/S '. ' L/L 'x' P/S ':' P/S '/' P/S '/' 'a' 'b' 'c' P/S '/' D/L '.' "..... ...XX XXX.. XX..X ..... X.X.X ..... X.X.. ..... X.X.. ...X. ...XX ..X.. ..... X.X.. XXXX. XX.X") // Uses Binary/Shift rather than Lower/Shift to save two bits. testHighLevelEncodeString(t, "ABCdEFG", //'A' 'B' 'C' B/S =1 'd' 'E' 'F' 'G' "...X. ...XX ..X.. XXXXX ....X .XX..X.. ..XX. ..XXX .X...") testHighLevelEncodeStringCnt(t, // Found on an airline boarding pass. Several stretches of Binary shift are // necessary to keep the bitcount so low. "09 UAG ^160MEUCIQC0sYS/HpKxnBELR1uB85R20OoqqwFGa0q2uEi"+ "Ygh6utAIgLl1aBVM4EOTQtMQQYH9M2Z3Dp4qnA/fwWuQ+M8L3V8U=", 823) } func Test_HighLevelEncodeBinary(t *testing.T) { // binary short form single byte testHighLevelEncodeString(t, "N\u0000N", // 'N' B/S =1 '\0' N ".XXXX XXXXX ....X ........ .XXXX") // Encode "N" in UPPER testHighLevelEncodeString(t, "N\u0000n", // 'N' B/S =2 '\0' 'n' ".XXXX XXXXX ...X. ........ .XX.XXX.") // Encode "n" in BINARY // binary short form consecutive bytes testHighLevelEncodeString(t, "N\x00\x80 A", // 'N' B/S =2 '\0' \u0080 ' ' 'A' ".XXXX XXXXX ...X. ........ X....... ....X ...X.") // binary skipping over single character testHighLevelEncodeString(t, "\x00a\xFF\x80 A", // B/S =4 '\0' 'a' '\3ff' '\200' ' ' 'A' "XXXXX ..X.. ........ .XX....X XXXXXXXX X....... ....X ...X.") // getting into binary mode from digit mode testHighLevelEncodeString(t, "1234\u0000", //D/L '1' '2' '3' '4' U/L B/S =1 \0 "XXXX. ..XX .X.. .X.X .XX. XXX. XXXXX ....X ........") // Create a string in which every character requires binary sb := new(bytes.Buffer) for i := 0; i <= 3000; i++ { sb.WriteByte(byte(128 + (i % 30))) } // Test the output generated by Binary/Switch, particularly near the // places where the encoding changes: 31, 62, and 2047+31=2078 for _, i := range []int{1, 2, 3, 10, 29, 30, 31, 32, 33, 60, 61, 62, 63, 64, 2076, 2077, 2078, 2079, 2080, 2100} { // This is the expected length of a binary string of length "i" expectedLength := (8 * i) switch { case i <= 31: expectedLength += 10 case i <= 62: expectedLength += 20 case i <= 2078: expectedLength += 21 default: expectedLength += 31 } data := string(sb.Bytes()[:i]) // Verify that we are correct about the length. testHighLevelEncodeStringCnt(t, data, expectedLength) if i != 1 && i != 32 && i != 2079 { // The addition of an 'a' at the beginning or end gets merged into the binary code // in those cases where adding another binary character only adds 8 or 9 bits to the result. // So we exclude the border cases i=1,32,2079 // A lower case letter at the beginning will be merged into binary mode testHighLevelEncodeStringCnt(t, "a"+string(sb.Bytes()[:i-1]), expectedLength) // A lower case letter at the end will also be merged into binary mode testHighLevelEncodeStringCnt(t, string(sb.Bytes()[:i-1])+"a", expectedLength) } // A lower case letter at both ends will enough to latch us into LOWER. testHighLevelEncodeStringCnt(t, "a"+data+"b", expectedLength+15) } } barcode-1.0.1/aztec/state.go000066400000000000000000000155531343272050500156770ustar00rootroot00000000000000package aztec import ( "fmt" "github.com/boombuler/barcode/utils" ) type encodingMode byte const ( mode_upper encodingMode = iota // 5 bits mode_lower // 5 bits mode_digit // 4 bits mode_mixed // 5 bits mode_punct // 5 bits ) var ( // The Latch Table shows, for each pair of Modes, the optimal method for // getting from one mode to another. In the worst possible case, this can // be up to 14 bits. In the best possible case, we are already there! // The high half-word of each entry gives the number of bits. // The low half-word of each entry are the actual bits necessary to change latchTable = map[encodingMode]map[encodingMode]int{ mode_upper: { mode_upper: 0, mode_lower: (5 << 16) + 28, mode_digit: (5 << 16) + 30, mode_mixed: (5 << 16) + 29, mode_punct: (10 << 16) + (29 << 5) + 30, }, mode_lower: { mode_upper: (9 << 16) + (30 << 4) + 14, mode_lower: 0, mode_digit: (5 << 16) + 30, mode_mixed: (5 << 16) + 29, mode_punct: (10 << 16) + (29 << 5) + 30, }, mode_digit: { mode_upper: (4 << 16) + 14, mode_lower: (9 << 16) + (14 << 5) + 28, mode_digit: 0, mode_mixed: (9 << 16) + (14 << 5) + 29, mode_punct: (14 << 16) + (14 << 10) + (29 << 5) + 30, }, mode_mixed: { mode_upper: (5 << 16) + 29, mode_lower: (5 << 16) + 28, mode_digit: (10 << 16) + (29 << 5) + 30, mode_mixed: 0, mode_punct: (5 << 16) + 30, }, mode_punct: { mode_upper: (5 << 16) + 31, mode_lower: (10 << 16) + (31 << 5) + 28, mode_digit: (10 << 16) + (31 << 5) + 30, mode_mixed: (10 << 16) + (31 << 5) + 29, mode_punct: 0, }, } // A map showing the available shift codes. (The shifts to BINARY are not shown) shiftTable = map[encodingMode]map[encodingMode]int{ mode_upper: { mode_punct: 0, }, mode_lower: { mode_punct: 0, mode_upper: 28, }, mode_mixed: { mode_punct: 0, }, mode_digit: { mode_punct: 0, mode_upper: 15, }, } charMap map[encodingMode][]int ) type state struct { mode encodingMode tokens token bShiftByteCount int bitCount int } type stateSlice []*state var initialState *state = &state{ mode: mode_upper, tokens: nil, bShiftByteCount: 0, bitCount: 0, } func init() { charMap = make(map[encodingMode][]int) charMap[mode_upper] = make([]int, 256) charMap[mode_lower] = make([]int, 256) charMap[mode_digit] = make([]int, 256) charMap[mode_mixed] = make([]int, 256) charMap[mode_punct] = make([]int, 256) charMap[mode_upper][' '] = 1 for c := 'A'; c <= 'Z'; c++ { charMap[mode_upper][int(c)] = int(c - 'A' + 2) } charMap[mode_lower][' '] = 1 for c := 'a'; c <= 'z'; c++ { charMap[mode_lower][c] = int(c - 'a' + 2) } charMap[mode_digit][' '] = 1 for c := '0'; c <= '9'; c++ { charMap[mode_digit][c] = int(c - '0' + 2) } charMap[mode_digit][','] = 12 charMap[mode_digit]['.'] = 13 mixedTable := []int{ 0, ' ', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 27, 28, 29, 30, 31, '@', '\\', '^', '_', '`', '|', '~', 127, } for i, v := range mixedTable { charMap[mode_mixed][v] = i } punctTable := []int{ 0, '\r', 0, 0, 0, 0, '!', '\'', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', ']', '{', '}', } for i, v := range punctTable { if v > 0 { charMap[mode_punct][v] = i } } } func (em encodingMode) BitCount() byte { if em == mode_digit { return 4 } return 5 } // Create a new state representing this state with a latch to a (not // necessary different) mode, and then a code. func (s *state) latchAndAppend(mode encodingMode, value int) *state { bitCount := s.bitCount tokens := s.tokens if mode != s.mode { latch := latchTable[s.mode][mode] tokens = newSimpleToken(tokens, latch&0xFFFF, byte(latch>>16)) bitCount += latch >> 16 } tokens = newSimpleToken(tokens, value, mode.BitCount()) return &state{ mode: mode, tokens: tokens, bShiftByteCount: 0, bitCount: bitCount + int(mode.BitCount()), } } // Create a new state representing this state, with a temporary shift // to a different mode to output a single value. func (s *state) shiftAndAppend(mode encodingMode, value int) *state { tokens := s.tokens // Shifts exist only to UPPER and PUNCT, both with tokens size 5. tokens = newSimpleToken(tokens, shiftTable[s.mode][mode], s.mode.BitCount()) tokens = newSimpleToken(tokens, value, 5) return &state{ mode: s.mode, tokens: tokens, bShiftByteCount: 0, bitCount: s.bitCount + int(s.mode.BitCount()) + 5, } } // Create a new state representing this state, but an additional character // output in Binary Shift mode. func (s *state) addBinaryShiftChar(index int) *state { tokens := s.tokens mode := s.mode bitCnt := s.bitCount if s.mode == mode_punct || s.mode == mode_digit { latch := latchTable[s.mode][mode_upper] tokens = newSimpleToken(tokens, latch&0xFFFF, byte(latch>>16)) bitCnt += latch >> 16 mode = mode_upper } deltaBitCount := 8 if s.bShiftByteCount == 0 || s.bShiftByteCount == 31 { deltaBitCount = 18 } else if s.bShiftByteCount == 62 { deltaBitCount = 9 } result := &state{ mode: mode, tokens: tokens, bShiftByteCount: s.bShiftByteCount + 1, bitCount: bitCnt + deltaBitCount, } if result.bShiftByteCount == 2047+31 { // The string is as long as it's allowed to be. We should end it. result = result.endBinaryShift(index + 1) } return result } // Create the state identical to this one, but we are no longer in // Binary Shift mode. func (s *state) endBinaryShift(index int) *state { if s.bShiftByteCount == 0 { return s } tokens := newShiftToken(s.tokens, index-s.bShiftByteCount, s.bShiftByteCount) return &state{ mode: s.mode, tokens: tokens, bShiftByteCount: 0, bitCount: s.bitCount, } } // Returns true if "this" state is better (or equal) to be in than "that" // state under all possible circumstances. func (this *state) isBetterThanOrEqualTo(other *state) bool { mySize := this.bitCount + (latchTable[this.mode][other.mode] >> 16) if other.bShiftByteCount > 0 && (this.bShiftByteCount == 0 || this.bShiftByteCount > other.bShiftByteCount) { mySize += 10 // Cost of entering Binary Shift mode. } return mySize <= other.bitCount } func (s *state) toBitList(text []byte) *utils.BitList { tokens := make([]token, 0) se := s.endBinaryShift(len(text)) for t := se.tokens; t != nil; t = t.prev() { tokens = append(tokens, t) } res := new(utils.BitList) for i := len(tokens) - 1; i >= 0; i-- { tokens[i].appendTo(res, text) } return res } func (s *state) String() string { tokens := make([]token, 0) for t := s.tokens; t != nil; t = t.prev() { tokens = append([]token{t}, tokens...) } return fmt.Sprintf("M:%d bits=%d bytes=%d: %v", s.mode, s.bitCount, s.bShiftByteCount, tokens) } barcode-1.0.1/aztec/token.go000066400000000000000000000034371343272050500156750ustar00rootroot00000000000000package aztec import ( "fmt" "github.com/boombuler/barcode/utils" ) type token interface { fmt.Stringer prev() token appendTo(bits *utils.BitList, text []byte) } type simpleToken struct { token value int bitCount byte } type binaryShiftToken struct { token bShiftStart int bShiftByteCnt int } func newSimpleToken(prev token, value int, bitCount byte) token { return &simpleToken{prev, value, bitCount} } func newShiftToken(prev token, bShiftStart int, bShiftCnt int) token { return &binaryShiftToken{prev, bShiftStart, bShiftCnt} } func (st *simpleToken) prev() token { return st.token } func (st *simpleToken) appendTo(bits *utils.BitList, text []byte) { bits.AddBits(st.value, st.bitCount) } func (st *simpleToken) String() string { value := st.value & ((1 << st.bitCount) - 1) value |= 1 << st.bitCount return "<" + fmt.Sprintf("%b", value)[1:] + ">" } func (bst *binaryShiftToken) prev() token { return bst.token } func (bst *binaryShiftToken) appendTo(bits *utils.BitList, text []byte) { for i := 0; i < bst.bShiftByteCnt; i++ { if i == 0 || (i == 31 && bst.bShiftByteCnt <= 62) { // We need a header before the first character, and before // character 31 when the total byte code is <= 62 bits.AddBits(31, 5) // BINARY_SHIFT if bst.bShiftByteCnt > 62 { bits.AddBits(bst.bShiftByteCnt-31, 16) } else if i == 0 { // 1 <= binaryShiftByteCode <= 62 if bst.bShiftByteCnt < 31 { bits.AddBits(bst.bShiftByteCnt, 5) } else { bits.AddBits(31, 5) } } else { // 32 <= binaryShiftCount <= 62 and i == 31 bits.AddBits(bst.bShiftByteCnt-31, 5) } } bits.AddByte(text[bst.bShiftStart+i]) } } func (bst *binaryShiftToken) String() string { return fmt.Sprintf("<%d::%d>", bst.bShiftStart, (bst.bShiftStart + bst.bShiftByteCnt - 1)) } barcode-1.0.1/barcode.go000066400000000000000000000017661343272050500150510ustar00rootroot00000000000000package barcode import "image" const ( TypeAztec = "Aztec" TypeCodabar = "Codabar" TypeCode128 = "Code 128" TypeCode39 = "Code 39" TypeCode93 = "Code 93" TypeDataMatrix = "DataMatrix" TypeEAN8 = "EAN 8" TypeEAN13 = "EAN 13" TypePDF = "PDF417" TypeQR = "QR Code" Type2of5 = "2 of 5" Type2of5Interleaved = "2 of 5 (interleaved)" ) // Contains some meta information about a barcode type Metadata struct { // the name of the barcode kind CodeKind string // contains 1 for 1D barcodes or 2 for 2D barcodes Dimensions byte } // a rendered and encoded barcode type Barcode interface { image.Image // returns some meta information about the barcode Metadata() Metadata // the data that was encoded in this barcode Content() string } // Additional interface that some barcodes might implement to provide // the value of its checksum. type BarcodeIntCS interface { Barcode CheckSum() int } barcode-1.0.1/codabar/000077500000000000000000000000001343272050500145045ustar00rootroot00000000000000barcode-1.0.1/codabar/encoder.go000066400000000000000000000042631343272050500164570ustar00rootroot00000000000000// Package codabar can create Codabar barcodes package codabar import ( "fmt" "regexp" "github.com/boombuler/barcode" "github.com/boombuler/barcode/utils" ) var encodingTable = map[rune][]bool{ '0': []bool{true, false, true, false, true, false, false, true, true}, '1': []bool{true, false, true, false, true, true, false, false, true}, '2': []bool{true, false, true, false, false, true, false, true, true}, '3': []bool{true, true, false, false, true, false, true, false, true}, '4': []bool{true, false, true, true, false, true, false, false, true}, '5': []bool{true, true, false, true, false, true, false, false, true}, '6': []bool{true, false, false, true, false, true, false, true, true}, '7': []bool{true, false, false, true, false, true, true, false, true}, '8': []bool{true, false, false, true, true, false, true, false, true}, '9': []bool{true, true, false, true, false, false, true, false, true}, '-': []bool{true, false, true, false, false, true, true, false, true}, '$': []bool{true, false, true, true, false, false, true, false, true}, ':': []bool{true, true, false, true, false, true, true, false, true, true}, '/': []bool{true, true, false, true, true, false, true, false, true, true}, '.': []bool{true, true, false, true, true, false, true, true, false, true}, '+': []bool{true, false, true, true, false, true, true, false, true, true}, 'A': []bool{true, false, true, true, false, false, true, false, false, true}, 'B': []bool{true, false, false, true, false, false, true, false, true, true}, 'C': []bool{true, false, true, false, false, true, false, false, true, true}, 'D': []bool{true, false, true, false, false, true, true, false, false, true}, } // Encode creates a codabar barcode for the given content func Encode(content string) (barcode.Barcode, error) { checkValid, _ := regexp.Compile(`[ABCD][0123456789\-\$\:/\.\+]*[ABCD]$`) if content == "!" || checkValid.ReplaceAllString(content, "!") != "!" { return nil, fmt.Errorf("can not encode \"%s\"", content) } resBits := new(utils.BitList) for i, r := range content { if i > 0 { resBits.AddBit(false) } resBits.AddBit(encodingTable[r]...) } return utils.New1DCode(barcode.TypeCodabar, content, resBits), nil } barcode-1.0.1/codabar/encoder_test.go000066400000000000000000000012631343272050500175130ustar00rootroot00000000000000package codabar import ( "image/color" "testing" ) func Test_Encode(t *testing.T) { _, err := Encode("FOOBAR") if err == nil { t.Error("\"FOOBAR\" should not be encodable") } testEncode := func(txt, testResult string) { code, err := Encode(txt) if err != nil || code == nil { t.Fail() } else { if code.Bounds().Max.X != len(testResult) { t.Errorf("%v: length missmatch", txt) } else { for i, r := range testResult { if (code.At(i, 0) == color.Black) != (r == '1') { t.Errorf("%v: code missmatch on position %d", txt, i) } } } } } testEncode("A40156B", "10110010010101101001010101001101010110010110101001010010101101001001011") } barcode-1.0.1/code128/000077500000000000000000000000001343272050500142565ustar00rootroot00000000000000barcode-1.0.1/code128/encode.go000066400000000000000000000106661343272050500160530ustar00rootroot00000000000000// Package code128 can create Code128 barcodes package code128 import ( "fmt" "strings" "unicode/utf8" "github.com/boombuler/barcode" "github.com/boombuler/barcode/utils" ) func strToRunes(str string) []rune { result := make([]rune, utf8.RuneCountInString(str)) i := 0 for _, r := range str { result[i] = r i++ } return result } func shouldUseCTable(nextRunes []rune, curEncoding byte) bool { requiredDigits := 4 if curEncoding == startCSymbol { requiredDigits = 2 } if len(nextRunes) < requiredDigits { return false } for i := 0; i < requiredDigits; i++ { if i%2 == 0 && nextRunes[i] == FNC1 { requiredDigits++ if len(nextRunes) < requiredDigits { return false } continue } if nextRunes[i] < '0' || nextRunes[i] > '9' { return false } } return true } func tableContainsRune(table string, r rune) bool { return strings.ContainsRune(table, r) || r == FNC1 || r == FNC2 || r == FNC3 || r == FNC4 } func shouldUseATable(nextRunes []rune, curEncoding byte) bool { nextRune := nextRunes[0] if !tableContainsRune(bTable, nextRune) || curEncoding == startASymbol { return tableContainsRune(aTable, nextRune) } if curEncoding == 0 { for _, r := range nextRunes { if tableContainsRune(abTable, r) { continue } if strings.ContainsRune(aOnlyTable, r) { return true } break } } return false } func getCodeIndexList(content []rune) *utils.BitList { result := new(utils.BitList) curEncoding := byte(0) for i := 0; i < len(content); i++ { if shouldUseCTable(content[i:], curEncoding) { if curEncoding != startCSymbol { if curEncoding == byte(0) { result.AddByte(startCSymbol) } else { result.AddByte(codeCSymbol) } curEncoding = startCSymbol } if content[i] == FNC1 { result.AddByte(102) } else { idx := (content[i] - '0') * 10 i++ idx = idx + (content[i] - '0') result.AddByte(byte(idx)) } } else if shouldUseATable(content[i:], curEncoding) { if curEncoding != startASymbol { if curEncoding == byte(0) { result.AddByte(startASymbol) } else { result.AddByte(codeASymbol) } curEncoding = startASymbol } var idx int switch content[i] { case FNC1: idx = 102 break case FNC2: idx = 97 break case FNC3: idx = 96 break case FNC4: idx = 101 break default: idx = strings.IndexRune(aTable, content[i]) break } if idx < 0 { return nil } result.AddByte(byte(idx)) } else { if curEncoding != startBSymbol { if curEncoding == byte(0) { result.AddByte(startBSymbol) } else { result.AddByte(codeBSymbol) } curEncoding = startBSymbol } var idx int switch content[i] { case FNC1: idx = 102 break case FNC2: idx = 97 break case FNC3: idx = 96 break case FNC4: idx = 100 break default: idx = strings.IndexRune(bTable, content[i]) break } if idx < 0 { return nil } result.AddByte(byte(idx)) } } return result } // Encode creates a Code 128 barcode for the given content func Encode(content string) (barcode.BarcodeIntCS, error) { contentRunes := strToRunes(content) if len(contentRunes) <= 0 || len(contentRunes) > 80 { return nil, fmt.Errorf("content length should be between 1 and 80 runes but got %d", len(contentRunes)) } idxList := getCodeIndexList(contentRunes) if idxList == nil { return nil, fmt.Errorf("\"%s\" could not be encoded", content) } result := new(utils.BitList) sum := 0 for i, idx := range idxList.GetBytes() { if i == 0 { sum = int(idx) } else { sum += i * int(idx) } result.AddBit(encodingTable[idx]...) } sum = sum % 103 result.AddBit(encodingTable[sum]...) result.AddBit(encodingTable[stopSymbol]...) return utils.New1DCodeIntCheckSum(barcode.TypeCode128, content, result, sum), nil } func EncodeWithoutChecksum(content string) (barcode.Barcode, error) { contentRunes := strToRunes(content) if len(contentRunes) <= 0 || len(contentRunes) > 80 { return nil, fmt.Errorf("content length should be between 1 and 80 runes but got %d", len(contentRunes)) } idxList := getCodeIndexList(contentRunes) if idxList == nil { return nil, fmt.Errorf("\"%s\" could not be encoded", content) } result := new(utils.BitList) for _, idx := range idxList.GetBytes() { result.AddBit(encodingTable[idx]...) } result.AddBit(encodingTable[stopSymbol]...) return utils.New1DCode(barcode.TypeCode128, content, result), nil } barcode-1.0.1/code128/encode_test.go000066400000000000000000000075711343272050500171130ustar00rootroot00000000000000package code128 import ( "image/color" "testing" ) func testEncode(t *testing.T, txt, testResult string) { code, err := Encode(txt) if err != nil || code == nil { t.Error(err) } else { if code.Bounds().Max.X != len(testResult) { t.Errorf("%v: length missmatch. Got %d expected %d", txt, code.Bounds().Max.X, len(testResult)) } else { encoded := "" failed := false for i, r := range testResult { if code.At(i, 0) == color.Black { encoded += "1" } else { encoded += "0" } if (code.At(i, 0) == color.Black) != (r == '1') { failed = true t.Errorf("%v: code missmatch on position %d", txt, i) } } if failed { t.Log("Encoded: ", encoded) } } } } func Test_EncodeFunctionChars(t *testing.T) { encFNC1 := "11110101110" encFNC2 := "11110101000" encFNC3 := "10111100010" encFNC4 := "10111101110" encStartB := "11010010000" encStop := "1100011101011" // Special Case FC1 can also be encoded to C Table therefor using 123 as suffix might have unexpected results. testEncode(t, string(FNC1)+"A23", encStartB+encFNC1+"10100011000"+"11001110010"+"11001011100"+"10100011110"+encStop) testEncode(t, string(FNC2)+"123", encStartB+encFNC2+"10011100110"+"11001110010"+"11001011100"+"11100010110"+encStop) testEncode(t, string(FNC3)+"123", encStartB+encFNC3+"10011100110"+"11001110010"+"11001011100"+"11101000110"+encStop) testEncode(t, string(FNC4)+"123", encStartB+encFNC4+"10011100110"+"11001110010"+"11001011100"+"11100011010"+encStop) } func Test_Unencodable(t *testing.T) { if _, err := Encode(""); err == nil { t.Fail() } if _, err := Encode("ä"); err == nil { t.Fail() } } func Test_EncodeCTable(t *testing.T) { testEncode(t, "HI345678H", "110100100001100010100011000100010101110111101000101100011100010110110000101001011110111011000101000111011000101100011101011") testEncode(t, "334455", "11010011100101000110001000110111011101000110100100111101100011101011") testEncode(t, string(FNC1)+"1234", "11010011100"+ // Start C "11110101110"+ // FNC1 "10110011100"+ // 12 "10001011000"+ // 34 "11101001100"+ // CheckSum == 24 "1100011101011") // Stop } func Test_shouldUseCTable(t *testing.T) { if !shouldUseCTable([]rune{FNC1, '1', '2'}, startCSymbol) { t.Error("[FNC1]12 failed") } if shouldUseCTable([]rune{FNC1, '1'}, startCSymbol) { t.Error("[FNC1]1 failed") } if shouldUseCTable([]rune{'0', FNC1, '1'}, startCSymbol) { t.Error("0[FNC1]1 failed") } if !shouldUseCTable([]rune{'0', '1', FNC1, '2', '3'}, startBSymbol) { t.Error("01[FNC1]23 failed") } if shouldUseCTable([]rune{'0', '1', FNC1}, startBSymbol) { t.Error("01[FNC1] failed") } } func Test_Issue16(t *testing.T) { if !shouldUseATable([]rune{'\r', 'A'}, 0) { t.Error("Code should start with A-Table if the text start with \\r") } if !shouldUseATable([]rune{FNC1, '\r'}, 0) { t.Error("Code should start with A-Table if the text start with \\r") } if shouldUseATable([]rune{FNC1, '1', '2', '3'}, 0) { t.Error("Code should not start with A-Table if the text start with 123") } testEncode(t, string(FNC3)+"$P\rI", "110100001001011110001010010001100111011101101111011101011000100010110001010001100011101011") } func Test_Datalogic(t *testing.T) { // $P\r testEncode(t, string(FNC3)+"$P\r", "11010000100"+ // "10111100010"+ // "10010001100"+ // $ "11101110110"+ // P "11110111010"+ // CR "11000100010"+ // checksum = 'I' "1100011101011") // STOP // $P,Ae,P testEncode(t, string(FNC3)+"$P,Ae,P\r", "11010010000"+ // "10111100010"+ // "10010001100"+ // $ "11101110110"+ // P "10110011100"+ // , "10100011000"+ // A "10110010000"+ // e "10110011100"+ // , "11101110110"+ // P "11101011110"+ // "11110111010"+ // "10110001000"+ // checksum = 'D' "1100011101011") // STOP } barcode-1.0.1/code128/encodingtable.go000066400000000000000000000227251343272050500174130ustar00rootroot00000000000000package code128 var encodingTable = [107][]bool{ []bool{true, true, false, true, true, false, false, true, true, false, false}, []bool{true, true, false, false, true, true, false, true, true, false, false}, []bool{true, true, false, false, true, true, false, false, true, true, false}, []bool{true, false, false, true, false, false, true, true, false, false, false}, []bool{true, false, false, true, false, false, false, true, true, false, false}, []bool{true, false, false, false, true, false, false, true, true, false, false}, []bool{true, false, false, true, true, false, false, true, false, false, false}, []bool{true, false, false, true, true, false, false, false, true, false, false}, []bool{true, false, false, false, true, true, false, false, true, false, false}, []bool{true, true, false, false, true, false, false, true, false, false, false}, []bool{true, true, false, false, true, false, false, false, true, false, false}, []bool{true, true, false, false, false, true, false, false, true, false, false}, []bool{true, false, true, true, false, false, true, true, true, false, false}, []bool{true, false, false, true, true, false, true, true, true, false, false}, []bool{true, false, false, true, true, false, false, true, true, true, false}, []bool{true, false, true, true, true, false, false, true, true, false, false}, []bool{true, false, false, true, true, true, false, true, true, false, false}, []bool{true, false, false, true, true, true, false, false, true, true, false}, []bool{true, true, false, false, true, true, true, false, false, true, false}, []bool{true, true, false, false, true, false, true, true, true, false, false}, []bool{true, true, false, false, true, false, false, true, true, true, false}, []bool{true, true, false, true, true, true, false, false, true, false, false}, []bool{true, true, false, false, true, true, true, false, true, false, false}, []bool{true, true, true, false, true, true, false, true, true, true, false}, []bool{true, true, true, false, true, false, false, true, true, false, false}, []bool{true, true, true, false, false, true, false, true, true, false, false}, []bool{true, true, true, false, false, true, false, false, true, true, false}, []bool{true, true, true, false, true, true, false, false, true, false, false}, []bool{true, true, true, false, false, true, true, false, true, false, false}, []bool{true, true, true, false, false, true, true, false, false, true, false}, []bool{true, true, false, true, true, false, true, true, false, false, false}, []bool{true, true, false, true, true, false, false, false, true, true, false}, []bool{true, true, false, false, false, true, true, false, true, true, false}, []bool{true, false, true, false, false, false, true, true, false, false, false}, []bool{true, false, false, false, true, false, true, true, false, false, false}, []bool{true, false, false, false, true, false, false, false, true, true, false}, []bool{true, false, true, true, false, false, false, true, false, false, false}, []bool{true, false, false, false, true, true, false, true, false, false, false}, []bool{true, false, false, false, true, true, false, false, false, true, false}, []bool{true, true, false, true, false, false, false, true, false, false, false}, []bool{true, true, false, false, false, true, false, true, false, false, false}, []bool{true, true, false, false, false, true, false, false, false, true, false}, []bool{true, false, true, true, false, true, true, true, false, false, false}, []bool{true, false, true, true, false, false, false, true, true, true, false}, []bool{true, false, false, false, true, true, false, true, true, true, false}, []bool{true, false, true, true, true, false, true, true, false, false, false}, []bool{true, false, true, true, true, false, false, false, true, true, false}, []bool{true, false, false, false, true, true, true, false, true, true, false}, []bool{true, true, true, false, true, true, true, false, true, true, false}, []bool{true, true, false, true, false, false, false, true, true, true, false}, []bool{true, true, false, false, false, true, false, true, true, true, false}, []bool{true, true, false, true, true, true, false, true, false, false, false}, []bool{true, true, false, true, true, true, false, false, false, true, false}, []bool{true, true, false, true, true, true, false, true, true, true, false}, []bool{true, true, true, false, true, false, true, true, false, false, false}, []bool{true, true, true, false, true, false, false, false, true, true, false}, []bool{true, true, true, false, false, false, true, false, true, true, false}, []bool{true, true, true, false, true, true, false, true, false, false, false}, []bool{true, true, true, false, true, true, false, false, false, true, false}, []bool{true, true, true, false, false, false, true, true, false, true, false}, []bool{true, true, true, false, true, true, true, true, false, true, false}, []bool{true, true, false, false, true, false, false, false, false, true, false}, []bool{true, true, true, true, false, false, false, true, false, true, false}, []bool{true, false, true, false, false, true, true, false, false, false, false}, []bool{true, false, true, false, false, false, false, true, true, false, false}, []bool{true, false, false, true, false, true, true, false, false, false, false}, []bool{true, false, false, true, false, false, false, false, true, true, false}, []bool{true, false, false, false, false, true, false, true, true, false, false}, []bool{true, false, false, false, false, true, false, false, true, true, false}, []bool{true, false, true, true, false, false, true, false, false, false, false}, []bool{true, false, true, true, false, false, false, false, true, false, false}, []bool{true, false, false, true, true, false, true, false, false, false, false}, []bool{true, false, false, true, true, false, false, false, false, true, false}, []bool{true, false, false, false, false, true, true, false, true, false, false}, []bool{true, false, false, false, false, true, true, false, false, true, false}, []bool{true, true, false, false, false, false, true, false, false, true, false}, []bool{true, true, false, false, true, false, true, false, false, false, false}, []bool{true, true, true, true, false, true, true, true, false, true, false}, []bool{true, true, false, false, false, false, true, false, true, false, false}, []bool{true, false, false, false, true, true, true, true, false, true, false}, []bool{true, false, true, false, false, true, true, true, true, false, false}, []bool{true, false, false, true, false, true, true, true, true, false, false}, []bool{true, false, false, true, false, false, true, true, true, true, false}, []bool{true, false, true, true, true, true, false, false, true, false, false}, []bool{true, false, false, true, true, true, true, false, true, false, false}, []bool{true, false, false, true, true, true, true, false, false, true, false}, []bool{true, true, true, true, false, true, false, false, true, false, false}, []bool{true, true, true, true, false, false, true, false, true, false, false}, []bool{true, true, true, true, false, false, true, false, false, true, false}, []bool{true, true, false, true, true, false, true, true, true, true, false}, []bool{true, true, false, true, true, true, true, false, true, true, false}, []bool{true, true, true, true, false, true, true, false, true, true, false}, []bool{true, false, true, false, true, true, true, true, false, false, false}, []bool{true, false, true, false, false, false, true, true, true, true, false}, []bool{true, false, false, false, true, false, true, true, true, true, false}, []bool{true, false, true, true, true, true, false, true, false, false, false}, []bool{true, false, true, true, true, true, false, false, false, true, false}, []bool{true, true, true, true, false, true, false, true, false, false, false}, []bool{true, true, true, true, false, true, false, false, false, true, false}, []bool{true, false, true, true, true, false, true, true, true, true, false}, []bool{true, false, true, true, true, true, false, true, true, true, false}, []bool{true, true, true, false, true, false, true, true, true, true, false}, []bool{true, true, true, true, false, true, false, true, true, true, false}, []bool{true, true, false, true, false, false, false, false, true, false, false}, []bool{true, true, false, true, false, false, true, false, false, false, false}, []bool{true, true, false, true, false, false, true, true, true, false, false}, []bool{true, true, false, false, false, true, true, true, false, true, false, true, true}, } const startASymbol byte = 103 const startBSymbol byte = 104 const startCSymbol byte = 105 const codeASymbol byte = 101 const codeBSymbol byte = 100 const codeCSymbol byte = 99 const stopSymbol byte = 106 const ( // FNC1 - Special Function 1 FNC1 = '\u00f1' // FNC2 - Special Function 2 FNC2 = '\u00f2' // FNC3 - Special Function 3 FNC3 = '\u00f3' // FNC4 - Special Function 4 FNC4 = '\u00f4' ) const abTable = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" const bTable = abTable + "`abcdefghijklmnopqrstuvwxyz{|}~\u007F" const aOnlyTable = "\u0000\u0001\u0002\u0003\u0004" + // NUL, SOH, STX, ETX, EOT "\u0005\u0006\u0007\u0008\u0009" + // ENQ, ACK, BEL, BS, HT "\u000A\u000B\u000C\u000D\u000E" + // LF, VT, FF, CR, SO "\u000F\u0010\u0011\u0012\u0013" + // SI, DLE, DC1, DC2, DC3 "\u0014\u0015\u0016\u0017\u0018" + // DC4, NAK, SYN, ETB, CAN "\u0019\u001A\u001B\u001C\u001D" + // EM, SUB, ESC, FS, GS "\u001E\u001F" // RS, US const aTable = abTable + aOnlyTable barcode-1.0.1/code39/000077500000000000000000000000001343272050500141775ustar00rootroot00000000000000barcode-1.0.1/code39/encoder.go000066400000000000000000000165641343272050500161610ustar00rootroot00000000000000// Package code39 can create Code39 barcodes package code39 import ( "errors" "strconv" "strings" "github.com/boombuler/barcode" "github.com/boombuler/barcode/utils" ) type encodeInfo struct { value int data []bool } var encodeTable = map[rune]encodeInfo{ '0': encodeInfo{0, []bool{true, false, true, false, false, true, true, false, true, true, false, true}}, '1': encodeInfo{1, []bool{true, true, false, true, false, false, true, false, true, false, true, true}}, '2': encodeInfo{2, []bool{true, false, true, true, false, false, true, false, true, false, true, true}}, '3': encodeInfo{3, []bool{true, true, false, true, true, false, false, true, false, true, false, true}}, '4': encodeInfo{4, []bool{true, false, true, false, false, true, true, false, true, false, true, true}}, '5': encodeInfo{5, []bool{true, true, false, true, false, false, true, true, false, true, false, true}}, '6': encodeInfo{6, []bool{true, false, true, true, false, false, true, true, false, true, false, true}}, '7': encodeInfo{7, []bool{true, false, true, false, false, true, false, true, true, false, true, true}}, '8': encodeInfo{8, []bool{true, true, false, true, false, false, true, false, true, true, false, true}}, '9': encodeInfo{9, []bool{true, false, true, true, false, false, true, false, true, true, false, true}}, 'A': encodeInfo{10, []bool{true, true, false, true, false, true, false, false, true, false, true, true}}, 'B': encodeInfo{11, []bool{true, false, true, true, false, true, false, false, true, false, true, true}}, 'C': encodeInfo{12, []bool{true, true, false, true, true, false, true, false, false, true, false, true}}, 'D': encodeInfo{13, []bool{true, false, true, false, true, true, false, false, true, false, true, true}}, 'E': encodeInfo{14, []bool{true, true, false, true, false, true, true, false, false, true, false, true}}, 'F': encodeInfo{15, []bool{true, false, true, true, false, true, true, false, false, true, false, true}}, 'G': encodeInfo{16, []bool{true, false, true, false, true, false, false, true, true, false, true, true}}, 'H': encodeInfo{17, []bool{true, true, false, true, false, true, false, false, true, true, false, true}}, 'I': encodeInfo{18, []bool{true, false, true, true, false, true, false, false, true, true, false, true}}, 'J': encodeInfo{19, []bool{true, false, true, false, true, true, false, false, true, true, false, true}}, 'K': encodeInfo{20, []bool{true, true, false, true, false, true, false, true, false, false, true, true}}, 'L': encodeInfo{21, []bool{true, false, true, true, false, true, false, true, false, false, true, true}}, 'M': encodeInfo{22, []bool{true, true, false, true, true, false, true, false, true, false, false, true}}, 'N': encodeInfo{23, []bool{true, false, true, false, true, true, false, true, false, false, true, true}}, 'O': encodeInfo{24, []bool{true, true, false, true, false, true, true, false, true, false, false, true}}, 'P': encodeInfo{25, []bool{true, false, true, true, false, true, true, false, true, false, false, true}}, 'Q': encodeInfo{26, []bool{true, false, true, false, true, false, true, true, false, false, true, true}}, 'R': encodeInfo{27, []bool{true, true, false, true, false, true, false, true, true, false, false, true}}, 'S': encodeInfo{28, []bool{true, false, true, true, false, true, false, true, true, false, false, true}}, 'T': encodeInfo{29, []bool{true, false, true, false, true, true, false, true, true, false, false, true}}, 'U': encodeInfo{30, []bool{true, true, false, false, true, false, true, false, true, false, true, true}}, 'V': encodeInfo{31, []bool{true, false, false, true, true, false, true, false, true, false, true, true}}, 'W': encodeInfo{32, []bool{true, true, false, false, true, true, false, true, false, true, false, true}}, 'X': encodeInfo{33, []bool{true, false, false, true, false, true, true, false, true, false, true, true}}, 'Y': encodeInfo{34, []bool{true, true, false, false, true, false, true, true, false, true, false, true}}, 'Z': encodeInfo{35, []bool{true, false, false, true, true, false, true, true, false, true, false, true}}, '-': encodeInfo{36, []bool{true, false, false, true, false, true, false, true, true, false, true, true}}, '.': encodeInfo{37, []bool{true, true, false, false, true, false, true, false, true, true, false, true}}, ' ': encodeInfo{38, []bool{true, false, false, true, true, false, true, false, true, true, false, true}}, '$': encodeInfo{39, []bool{true, false, false, true, false, false, true, false, false, true, false, true}}, '/': encodeInfo{40, []bool{true, false, false, true, false, false, true, false, true, false, false, true}}, '+': encodeInfo{41, []bool{true, false, false, true, false, true, false, false, true, false, false, true}}, '%': encodeInfo{42, []bool{true, false, true, false, false, true, false, false, true, false, false, true}}, '*': encodeInfo{-1, []bool{true, false, false, true, false, true, true, false, true, true, false, true}}, } var extendedTable = map[rune]string{ 0: `%U`, 1: `$A`, 2: `$B`, 3: `$C`, 4: `$D`, 5: `$E`, 6: `$F`, 7: `$G`, 8: `$H`, 9: `$I`, 10: `$J`, 11: `$K`, 12: `$L`, 13: `$M`, 14: `$N`, 15: `$O`, 16: `$P`, 17: `$Q`, 18: `$R`, 19: `$S`, 20: `$T`, 21: `$U`, 22: `$V`, 23: `$W`, 24: `$X`, 25: `$Y`, 26: `$Z`, 27: `%A`, 28: `%B`, 29: `%C`, 30: `%D`, 31: `%E`, 33: `/A`, 34: `/B`, 35: `/C`, 36: `/D`, 37: `/E`, 38: `/F`, 39: `/G`, 40: `/H`, 41: `/I`, 42: `/J`, 43: `/K`, 44: `/L`, 47: `/O`, 58: `/Z`, 59: `%F`, 60: `%G`, 61: `%H`, 62: `%I`, 63: `%J`, 64: `%V`, 91: `%K`, 92: `%L`, 93: `%M`, 94: `%N`, 95: `%O`, 96: `%W`, 97: `+A`, 98: `+B`, 99: `+C`, 100: `+D`, 101: `+E`, 102: `+F`, 103: `+G`, 104: `+H`, 105: `+I`, 106: `+J`, 107: `+K`, 108: `+L`, 109: `+M`, 110: `+N`, 111: `+O`, 112: `+P`, 113: `+Q`, 114: `+R`, 115: `+S`, 116: `+T`, 117: `+U`, 118: `+V`, 119: `+W`, 120: `+X`, 121: `+Y`, 122: `+Z`, 123: `%P`, 124: `%Q`, 125: `%R`, 126: `%S`, 127: `%T`, } func getChecksum(content string) string { sum := 0 for _, r := range content { info, ok := encodeTable[r] if !ok || info.value < 0 { return "#" } sum += info.value } sum = sum % 43 for r, v := range encodeTable { if v.value == sum { return string(r) } } return "#" } func prepare(content string) (string, error) { result := "" for _, r := range content { if r > 127 { return "", errors.New("Only ASCII strings can be encoded") } val, ok := extendedTable[r] if ok { result += val } else { result += string([]rune{r}) } } return result, nil } // Encode returns a code39 barcode for the given content // if includeChecksum is set to true, a checksum character is calculated and added to the content func Encode(content string, includeChecksum bool, fullASCIIMode bool) (barcode.BarcodeIntCS, error) { if fullASCIIMode { var err error content, err = prepare(content) if err != nil { return nil, err } } else if strings.ContainsRune(content, '*') { return nil, errors.New("invalid data! try full ascii mode") } data := "*" + content if includeChecksum { data += getChecksum(content) } data += "*" result := new(utils.BitList) for i, r := range data { if i != 0 { result.AddBit(false) } info, ok := encodeTable[r] if !ok { return nil, errors.New("invalid data! try full ascii mode") } result.AddBit(info.data...) } checkSum, err := strconv.ParseInt(getChecksum(content), 10, 64) if err != nil { checkSum = 0 } return utils.New1DCodeIntCheckSum(barcode.TypeCode39, content, result, int(checkSum)), nil } barcode-1.0.1/code39/encoder_test.go000066400000000000000000000021341343272050500172040ustar00rootroot00000000000000package code39 import ( "image/color" "testing" ) func doTest(t *testing.T, addCS, fullASCII bool, data, testResult string) { code, err := Encode(data, addCS, fullASCII) if err != nil { t.Error(err) } if len(testResult) != code.Bounds().Max.X { t.Errorf("Invalid code size. Expected %d got %d", len(testResult), code.Bounds().Max.X) } for i, r := range testResult { if (code.At(i, 0) == color.Black) != (r == '1') { t.Errorf("Failed at position %d", i) } } } func Test_Encode(t *testing.T) { doTest(t, false, false, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", "1001011011010110101001011010110100101101101101001010101011001011011010110010101"+ "011011001010101010011011011010100110101011010011010101011001101011010101001101011010"+ "100110110110101001010101101001101101011010010101101101001010101011001101101010110010"+ "101101011001010101101100101100101010110100110101011011001101010101001011010110110010"+ "110101010011011010101010011011010110100101011010110010101101101100101010101001101011"+ "011010011010101011001101010101001011011011010010110101011001011010100101101101") } barcode-1.0.1/code93/000077500000000000000000000000001343272050500141775ustar00rootroot00000000000000barcode-1.0.1/code93/encoder.go000066400000000000000000000107051343272050500161500ustar00rootroot00000000000000// Package code93 can create Code93 barcodes package code93 import ( "errors" "strings" "github.com/boombuler/barcode" "github.com/boombuler/barcode/utils" ) type encodeInfo struct { value int data int } const ( // Special Function 1 ($) FNC1 = '\u00f1' // Special Function 2 (%) FNC2 = '\u00f2' // Special Function 3 (/) FNC3 = '\u00f3' // Special Function 4 (+) FNC4 = '\u00f4' ) var encodeTable = map[rune]encodeInfo{ '0': encodeInfo{0, 0x114}, '1': encodeInfo{1, 0x148}, '2': encodeInfo{2, 0x144}, '3': encodeInfo{3, 0x142}, '4': encodeInfo{4, 0x128}, '5': encodeInfo{5, 0x124}, '6': encodeInfo{6, 0x122}, '7': encodeInfo{7, 0x150}, '8': encodeInfo{8, 0x112}, '9': encodeInfo{9, 0x10A}, 'A': encodeInfo{10, 0x1A8}, 'B': encodeInfo{11, 0x1A4}, 'C': encodeInfo{12, 0x1A2}, 'D': encodeInfo{13, 0x194}, 'E': encodeInfo{14, 0x192}, 'F': encodeInfo{15, 0x18A}, 'G': encodeInfo{16, 0x168}, 'H': encodeInfo{17, 0x164}, 'I': encodeInfo{18, 0x162}, 'J': encodeInfo{19, 0x134}, 'K': encodeInfo{20, 0x11A}, 'L': encodeInfo{21, 0x158}, 'M': encodeInfo{22, 0x14C}, 'N': encodeInfo{23, 0x146}, 'O': encodeInfo{24, 0x12C}, 'P': encodeInfo{25, 0x116}, 'Q': encodeInfo{26, 0x1B4}, 'R': encodeInfo{27, 0x1B2}, 'S': encodeInfo{28, 0x1AC}, 'T': encodeInfo{29, 0x1A6}, 'U': encodeInfo{30, 0x196}, 'V': encodeInfo{31, 0x19A}, 'W': encodeInfo{32, 0x16C}, 'X': encodeInfo{33, 0x166}, 'Y': encodeInfo{34, 0x136}, 'Z': encodeInfo{35, 0x13A}, '-': encodeInfo{36, 0x12E}, '.': encodeInfo{37, 0x1D4}, ' ': encodeInfo{38, 0x1D2}, '$': encodeInfo{39, 0x1CA}, '/': encodeInfo{40, 0x16E}, '+': encodeInfo{41, 0x176}, '%': encodeInfo{42, 0x1AE}, FNC1: encodeInfo{43, 0x126}, FNC2: encodeInfo{44, 0x1DA}, FNC3: encodeInfo{45, 0x1D6}, FNC4: encodeInfo{46, 0x132}, '*': encodeInfo{47, 0x15E}, } var extendedTable = []string{ "\u00f2U", "\u00f1A", "\u00f1B", "\u00f1C", "\u00f1D", "\u00f1E", "\u00f1F", "\u00f1G", "\u00f1H", "\u00f1I", "\u00f1J", "\u00f1K", "\u00f1L", "\u00f1M", "\u00f1N", "\u00f1O", "\u00f1P", "\u00f1Q", "\u00f1R", "\u00f1S", "\u00f1T", "\u00f1U", "\u00f1V", "\u00f1W", "\u00f1X", "\u00f1Y", "\u00f1Z", "\u00f2A", "\u00f2B", "\u00f2C", "\u00f2D", "\u00f2E", " ", "\u00f3A", "\u00f3B", "\u00f3C", "\u00f3D", "\u00f3E", "\u00f3F", "\u00f3G", "\u00f3H", "\u00f3I", "\u00f3J", "\u00f3K", "\u00f3L", "-", ".", "\u00f3O", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "\u00f3Z", "\u00f2F", "\u00f2G", "\u00f2H", "\u00f2I", "\u00f2J", "\u00f2V", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "\u00f2K", "\u00f2L", "\u00f2M", "\u00f2N", "\u00f2O", "\u00f2W", "\u00f4A", "\u00f4B", "\u00f4C", "\u00f4D", "\u00f4E", "\u00f4F", "\u00f4G", "\u00f4H", "\u00f4I", "\u00f4J", "\u00f4K", "\u00f4L", "\u00f4M", "\u00f4N", "\u00f4O", "\u00f4P", "\u00f4Q", "\u00f4R", "\u00f4S", "\u00f4T", "\u00f4U", "\u00f4V", "\u00f4W", "\u00f4X", "\u00f4Y", "\u00f4Z", "\u00f2P", "\u00f2Q", "\u00f2R", "\u00f2S", "\u00f2T", } func prepare(content string) (string, error) { result := "" for _, r := range content { if r > 127 { return "", errors.New("Only ASCII strings can be encoded") } result += extendedTable[int(r)] } return result, nil } // Encode returns a code93 barcode for the given content // if includeChecksum is set to true, two checksum characters are calculated and added to the content func Encode(content string, includeChecksum bool, fullASCIIMode bool) (barcode.Barcode, error) { if fullASCIIMode { var err error content, err = prepare(content) if err != nil { return nil, err } } else if strings.ContainsRune(content, '*') { return nil, errors.New("invalid data! content may not contain '*'") } data := content + string(getChecksum(content, 20)) data += string(getChecksum(data, 15)) data = "*" + data + "*" result := new(utils.BitList) for _, r := range data { info, ok := encodeTable[r] if !ok { return nil, errors.New("invalid data!") } result.AddBits(info.data, 9) } result.AddBit(true) return utils.New1DCode(barcode.TypeCode93, content, result), nil } func getChecksum(content string, maxWeight int) rune { weight := 1 total := 0 data := []rune(content) for i := len(data) - 1; i >= 0; i-- { r := data[i] info, ok := encodeTable[r] if !ok { return ' ' } total += info.value * weight if weight++; weight > maxWeight { weight = 1 } } total = total % 47 for r, info := range encodeTable { if info.value == total { return r } } return ' ' } barcode-1.0.1/code93/encoder_test.go000066400000000000000000000022301343272050500172010ustar00rootroot00000000000000package code93 import ( "image/color" "testing" ) func doTest(t *testing.T, data, testResult string) { code, err := Encode(data, true, false) if err != nil { t.Error(err) } if len(testResult) != code.Bounds().Max.X { t.Errorf("Invalid code size. Expected %d got %d", len(testResult), code.Bounds().Max.X) } for i, r := range testResult { if (code.At(i, 0) == color.Black) != (r == '1') { t.Errorf("Failed at position %d", i) } } } func Test_CheckSum(t *testing.T) { if r := getChecksum("TEST93", 20); r != '+' { t.Errorf("Checksum C-Failed. Got %s", string(r)) } if r := getChecksum("TEST93+", 15); r != '6' { t.Errorf("Checksum K-Failed. Got %s", string(r)) } } func Test_Encode(t *testing.T) { doTest(t, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", "1010111101101010001101001001101000101100101001100100101100010101011010001011001"+ "001011000101001101001000110101010110001010011001010001101001011001000101101101101001"+ "101100101101011001101001101100101101100110101011011001011001101001101101001110101000"+ "101001010010001010001001010000101001010001001001001001000101010100001000100101000010"+ "101001110101010000101010111101") } barcode-1.0.1/datamatrix/000077500000000000000000000000001343272050500152475ustar00rootroot00000000000000barcode-1.0.1/datamatrix/codelayout.go000066400000000000000000000137001343272050500177470ustar00rootroot00000000000000package datamatrix import ( "github.com/boombuler/barcode/utils" "strconv" ) type setValFunc func(byte) type codeLayout struct { matrix *utils.BitList occupy *utils.BitList size *dmCodeSize } func newCodeLayout(size *dmCodeSize) *codeLayout { result := new(codeLayout) result.matrix = utils.NewBitList(size.MatrixColumns() * size.MatrixRows()) result.occupy = utils.NewBitList(size.MatrixColumns() * size.MatrixRows()) result.size = size return result } func (l *codeLayout) Occupied(row, col int) bool { return l.occupy.GetBit(col + row*l.size.MatrixColumns()) } func (l *codeLayout) Set(row, col int, value, bitNum byte) { val := ((value >> (7 - bitNum)) & 1) == 1 if row < 0 { row += l.size.MatrixRows() col += 4 - ((l.size.MatrixRows() + 4) % 8) } if col < 0 { col += l.size.MatrixColumns() row += 4 - ((l.size.MatrixColumns() + 4) % 8) } if l.Occupied(row, col) { panic("Field already occupied row: " + strconv.Itoa(row) + " col: " + strconv.Itoa(col)) } l.occupy.SetBit(col+row*l.size.MatrixColumns(), true) l.matrix.SetBit(col+row*l.size.MatrixColumns(), val) } func (l *codeLayout) SetSimple(row, col int, value byte) { l.Set(row-2, col-2, value, 0) l.Set(row-2, col-1, value, 1) l.Set(row-1, col-2, value, 2) l.Set(row-1, col-1, value, 3) l.Set(row-1, col-0, value, 4) l.Set(row-0, col-2, value, 5) l.Set(row-0, col-1, value, 6) l.Set(row-0, col-0, value, 7) } func (l *codeLayout) Corner1(value byte) { l.Set(l.size.MatrixRows()-1, 0, value, 0) l.Set(l.size.MatrixRows()-1, 1, value, 1) l.Set(l.size.MatrixRows()-1, 2, value, 2) l.Set(0, l.size.MatrixColumns()-2, value, 3) l.Set(0, l.size.MatrixColumns()-1, value, 4) l.Set(1, l.size.MatrixColumns()-1, value, 5) l.Set(2, l.size.MatrixColumns()-1, value, 6) l.Set(3, l.size.MatrixColumns()-1, value, 7) } func (l *codeLayout) Corner2(value byte) { l.Set(l.size.MatrixRows()-3, 0, value, 0) l.Set(l.size.MatrixRows()-2, 0, value, 1) l.Set(l.size.MatrixRows()-1, 0, value, 2) l.Set(0, l.size.MatrixColumns()-4, value, 3) l.Set(0, l.size.MatrixColumns()-3, value, 4) l.Set(0, l.size.MatrixColumns()-2, value, 5) l.Set(0, l.size.MatrixColumns()-1, value, 6) l.Set(1, l.size.MatrixColumns()-1, value, 7) } func (l *codeLayout) Corner3(value byte) { l.Set(l.size.MatrixRows()-3, 0, value, 0) l.Set(l.size.MatrixRows()-2, 0, value, 1) l.Set(l.size.MatrixRows()-1, 0, value, 2) l.Set(0, l.size.MatrixColumns()-2, value, 3) l.Set(0, l.size.MatrixColumns()-1, value, 4) l.Set(1, l.size.MatrixColumns()-1, value, 5) l.Set(2, l.size.MatrixColumns()-1, value, 6) l.Set(3, l.size.MatrixColumns()-1, value, 7) } func (l *codeLayout) Corner4(value byte) { l.Set(l.size.MatrixRows()-1, 0, value, 0) l.Set(l.size.MatrixRows()-1, l.size.MatrixColumns()-1, value, 1) l.Set(0, l.size.MatrixColumns()-3, value, 2) l.Set(0, l.size.MatrixColumns()-2, value, 3) l.Set(0, l.size.MatrixColumns()-1, value, 4) l.Set(1, l.size.MatrixColumns()-3, value, 5) l.Set(1, l.size.MatrixColumns()-2, value, 6) l.Set(1, l.size.MatrixColumns()-1, value, 7) } func (l *codeLayout) SetValues(data []byte) { idx := 0 row := 4 col := 0 for (row < l.size.MatrixRows()) || (col < l.size.MatrixColumns()) { if (row == l.size.MatrixRows()) && (col == 0) { l.Corner1(data[idx]) idx++ } if (row == l.size.MatrixRows()-2) && (col == 0) && (l.size.MatrixColumns()%4 != 0) { l.Corner2(data[idx]) idx++ } if (row == l.size.MatrixRows()-2) && (col == 0) && (l.size.MatrixColumns()%8 == 4) { l.Corner3(data[idx]) idx++ } if (row == l.size.MatrixRows()+4) && (col == 2) && (l.size.MatrixColumns()%8 == 0) { l.Corner4(data[idx]) idx++ } for true { if (row < l.size.MatrixRows()) && (col >= 0) && !l.Occupied(row, col) { l.SetSimple(row, col, data[idx]) idx++ } row -= 2 col += 2 if (row < 0) || (col >= l.size.MatrixColumns()) { break } } row += 1 col += 3 for true { if (row >= 0) && (col < l.size.MatrixColumns()) && !l.Occupied(row, col) { l.SetSimple(row, col, data[idx]) idx++ } row += 2 col -= 2 if (row >= l.size.MatrixRows()) || (col < 0) { break } } row += 3 col += 1 } if !l.Occupied(l.size.MatrixRows()-1, l.size.MatrixColumns()-1) { l.Set(l.size.MatrixRows()-1, l.size.MatrixColumns()-1, 255, 0) l.Set(l.size.MatrixRows()-2, l.size.MatrixColumns()-2, 255, 0) } } func (l *codeLayout) Merge() *datamatrixCode { result := newDataMatrixCode(l.size) //dotted horizontal lines for r := 0; r < l.size.Rows; r += (l.size.RegionRows() + 2) { for c := 0; c < l.size.Columns; c += 2 { result.set(c, r, true) } } //solid horizontal line for r := l.size.RegionRows() + 1; r < l.size.Rows; r += (l.size.RegionRows() + 2) { for c := 0; c < l.size.Columns; c++ { result.set(c, r, true) } } //dotted vertical lines for c := l.size.RegionColumns() + 1; c < l.size.Columns; c += (l.size.RegionColumns() + 2) { for r := 1; r < l.size.Rows; r += 2 { result.set(c, r, true) } } //solid vertical line for c := 0; c < l.size.Columns; c += (l.size.RegionColumns() + 2) { for r := 0; r < l.size.Rows; r++ { result.set(c, r, true) } } count := 0 for hRegion := 0; hRegion < l.size.RegionCountHorizontal; hRegion++ { for vRegion := 0; vRegion < l.size.RegionCountVertical; vRegion++ { for x := 0; x < l.size.RegionColumns(); x++ { colMatrix := (l.size.RegionColumns() * hRegion) + x colResult := ((2 + l.size.RegionColumns()) * hRegion) + x + 1 for y := 0; y < l.size.RegionRows(); y++ { rowMatrix := (l.size.RegionRows() * vRegion) + y rowResult := ((2 + l.size.RegionRows()) * vRegion) + y + 1 val := l.matrix.GetBit(colMatrix + rowMatrix*l.size.MatrixColumns()) if val { count++ } result.set(colResult, rowResult, val) } } } } return result } barcode-1.0.1/datamatrix/codesize.go000066400000000000000000000037751343272050500174170ustar00rootroot00000000000000package datamatrix type dmCodeSize struct { Rows int Columns int RegionCountHorizontal int RegionCountVertical int ECCCount int BlockCount int } func (s *dmCodeSize) RegionRows() int { return (s.Rows - (s.RegionCountHorizontal * 2)) / s.RegionCountHorizontal } func (s *dmCodeSize) RegionColumns() int { return (s.Columns - (s.RegionCountVertical * 2)) / s.RegionCountVertical } func (s *dmCodeSize) MatrixRows() int { return s.RegionRows() * s.RegionCountHorizontal } func (s *dmCodeSize) MatrixColumns() int { return s.RegionColumns() * s.RegionCountVertical } func (s *dmCodeSize) DataCodewords() int { return ((s.MatrixColumns() * s.MatrixRows()) / 8) - s.ECCCount } func (s *dmCodeSize) DataCodewordsForBlock(idx int) int { if s.Rows == 144 && s.Columns == 144 { // Special Case... if idx < 8 { return 156 } else { return 155 } } return s.DataCodewords() / s.BlockCount } func (s *dmCodeSize) ErrorCorrectionCodewordsPerBlock() int { return s.ECCCount / s.BlockCount } var codeSizes []*dmCodeSize = []*dmCodeSize{ &dmCodeSize{10, 10, 1, 1, 5, 1}, &dmCodeSize{12, 12, 1, 1, 7, 1}, &dmCodeSize{14, 14, 1, 1, 10, 1}, &dmCodeSize{16, 16, 1, 1, 12, 1}, &dmCodeSize{18, 18, 1, 1, 14, 1}, &dmCodeSize{20, 20, 1, 1, 18, 1}, &dmCodeSize{22, 22, 1, 1, 20, 1}, &dmCodeSize{24, 24, 1, 1, 24, 1}, &dmCodeSize{26, 26, 1, 1, 28, 1}, &dmCodeSize{32, 32, 2, 2, 36, 1}, &dmCodeSize{36, 36, 2, 2, 42, 1}, &dmCodeSize{40, 40, 2, 2, 48, 1}, &dmCodeSize{44, 44, 2, 2, 56, 1}, &dmCodeSize{48, 48, 2, 2, 68, 1}, &dmCodeSize{52, 52, 2, 2, 84, 2}, &dmCodeSize{64, 64, 4, 4, 112, 2}, &dmCodeSize{72, 72, 4, 4, 144, 4}, &dmCodeSize{80, 80, 4, 4, 192, 4}, &dmCodeSize{88, 88, 4, 4, 224, 4}, &dmCodeSize{96, 96, 4, 4, 272, 4}, &dmCodeSize{104, 104, 4, 4, 336, 6}, &dmCodeSize{120, 120, 6, 6, 408, 6}, &dmCodeSize{132, 132, 6, 6, 496, 8}, &dmCodeSize{144, 144, 6, 6, 620, 10}, } barcode-1.0.1/datamatrix/datamatrix_test.go000066400000000000000000000045251343272050500210010ustar00rootroot00000000000000package datamatrix import ( "bytes" "testing" ) func codeFromStr(str string, size *dmCodeSize) *datamatrixCode { code := newDataMatrixCode(size) idx := 0 for _, r := range str { x := idx % size.Columns y := idx / size.Columns switch r { case '#': code.set(x, y, true) case '.': code.set(x, y, false) default: continue } idx++ } return code } func Test_Issue12(t *testing.T) { data := `{"po":12,"batchAction":"start_end"}` realData := addPadding(encodeText(data), 36) wantedData := []byte{124, 35, 113, 112, 35, 59, 142, 45, 35, 99, 98, 117, 100, 105, 66, 100, 117, 106, 112, 111, 35, 59, 35, 116, 117, 98, 115, 117, 96, 102, 111, 101, 35, 126, 129, 181} if bytes.Compare(realData, wantedData) != 0 { t.Error("Data Encoding failed") return } var codeSize *dmCodeSize for _, s := range codeSizes { if s.DataCodewords() >= len(wantedData) { codeSize = s break } } realECC := ec.calcECC(realData, codeSize)[len(realData):] wantedECC := []byte{196, 53, 147, 192, 151, 213, 107, 61, 98, 251, 50, 71, 186, 15, 43, 111, 165, 243, 209, 79, 128, 109, 251, 4} if bytes.Compare(realECC, wantedECC) != 0 { t.Errorf("Error correction calculation failed\nGot: %v", realECC) return } barcode := ` #.#.#.#.#.#.#.#.#.#.#.#. #....###..#..#....#...## ##.......#...#.#.#....#. #.###...##..#...##.##..# ##...####..##..#.#.#.##. #.###.##.###..#######.## #..###...##.##..#.##.##. #.#.#.#.#.#.###....#.#.# ##.#...#.#.#..#...#####. #...####..#...##..#.#..# ##...#...##.###.#.....#. #.###.#.##.#.....###..## ##..#####...#..##...###. ###...#.####.##.#.#.#..# #..###..#.#.####.#.###.. ###.#.#..#..#.###.#.##.# #####.##.###..#.####.#.. #.##.#......#.#..#.#.### ###.#....######.#...##.. ##...#..##.###..#...#### #.######.###.##..#...##. #..#..#.##.#..####...#.# ###.###..#..##.#.##...#. ########################` bc, err := Encode(data) if err != nil { t.Error(err) return } realResult := bc.(*datamatrixCode) if realResult.Columns != 24 || realResult.Rows != 24 { t.Errorf("Got wrong barcode size %dx%d", realResult.Columns, realResult.Rows) return } wantedResult := codeFromStr(barcode, realResult.dmCodeSize) for x := 0; x < wantedResult.Columns; x++ { for y := 0; y < wantedResult.Rows; y++ { r := realResult.get(x, y) w := wantedResult.get(x, y) if w != r { t.Errorf("Failed at: c%d/r%d", x, y) } } } } barcode-1.0.1/datamatrix/datamatrixcode.go000066400000000000000000000020061343272050500205650ustar00rootroot00000000000000package datamatrix import ( "image" "image/color" "github.com/boombuler/barcode" "github.com/boombuler/barcode/utils" ) type datamatrixCode struct { *utils.BitList *dmCodeSize content string } func newDataMatrixCode(size *dmCodeSize) *datamatrixCode { return &datamatrixCode{utils.NewBitList(size.Rows * size.Columns), size, ""} } func (c *datamatrixCode) Content() string { return c.content } func (c *datamatrixCode) Metadata() barcode.Metadata { return barcode.Metadata{barcode.TypeDataMatrix, 2} } func (c *datamatrixCode) ColorModel() color.Model { return color.Gray16Model } func (c *datamatrixCode) Bounds() image.Rectangle { return image.Rect(0, 0, c.Columns, c.Rows) } func (c *datamatrixCode) At(x, y int) color.Color { if c.get(x, y) { return color.Black } return color.White } func (c *datamatrixCode) get(x, y int) bool { return c.GetBit(x*c.Rows + y) } func (c *datamatrixCode) set(x, y int, value bool) { c.SetBit(x*c.Rows+y, value) } barcode-1.0.1/datamatrix/encoder.go000066400000000000000000000030621343272050500172160ustar00rootroot00000000000000// Package datamatrix can create Datamatrix barcodes package datamatrix import ( "errors" "github.com/boombuler/barcode" ) // Encode returns a Datamatrix barcode for the given content func Encode(content string) (barcode.Barcode, error) { data := encodeText(content) var size *dmCodeSize for _, s := range codeSizes { if s.DataCodewords() >= len(data) { size = s break } } if size == nil { return nil, errors.New("to much data to encode") } data = addPadding(data, size.DataCodewords()) data = ec.calcECC(data, size) code := render(data, size) if code != nil { code.content = content return code, nil } return nil, errors.New("unable to render barcode") } func render(data []byte, size *dmCodeSize) *datamatrixCode { cl := newCodeLayout(size) cl.SetValues(data) return cl.Merge() } func encodeText(content string) []byte { var result []byte input := []byte(content) for i := 0; i < len(input); { c := input[i] i++ if c >= '0' && c <= '9' && i < len(input) && input[i] >= '0' && input[i] <= '9' { // two numbers... c2 := input[i] i++ cw := byte(((c-'0')*10 + (c2 - '0')) + 130) result = append(result, cw) } else if c > 127 { // not correct... needs to be redone later... result = append(result, 235, c-127) } else { result = append(result, c+1) } } return result } func addPadding(data []byte, toCount int) []byte { if len(data) < toCount { data = append(data, 129) } for len(data) < toCount { R := ((149 * (len(data) + 1)) % 253) + 1 data = append(data, byte((129+R)%254)) } return data } barcode-1.0.1/datamatrix/errorcorrection.go000066400000000000000000000022221343272050500210150ustar00rootroot00000000000000package datamatrix import ( "github.com/boombuler/barcode/utils" ) type errorCorrection struct { rs *utils.ReedSolomonEncoder } var ec *errorCorrection = newErrorCorrection() func newErrorCorrection() *errorCorrection { gf := utils.NewGaloisField(301, 256, 1) return &errorCorrection{utils.NewReedSolomonEncoder(gf)} } func (ec *errorCorrection) calcECC(data []byte, size *dmCodeSize) []byte { dataSize := len(data) // make some space for error correction codes data = append(data, make([]byte, size.ECCCount)...) for block := 0; block < size.BlockCount; block++ { dataCnt := size.DataCodewordsForBlock(block) buff := make([]int, dataCnt) // copy the data for the current block to buff j := 0 for i := block; i < dataSize; i += size.BlockCount { buff[j] = int(data[i]) j++ } // calc the error correction codes ecc := ec.rs.Encode(buff, size.ErrorCorrectionCodewordsPerBlock()) // and append them to the result j = 0 for i := block; i < size.ErrorCorrectionCodewordsPerBlock()*size.BlockCount; i += size.BlockCount { data[dataSize+i] = byte(ecc[j]) j++ } } return data } barcode-1.0.1/datamatrix/errorcorrection_test.go000066400000000000000000000010771343272050500220630ustar00rootroot00000000000000package datamatrix import ( "bytes" "testing" ) func Test_CalcECC(t *testing.T) { data := []byte{142, 164, 186} var size *dmCodeSize = nil for _, s := range codeSizes { if s.DataCodewords() >= len(data) { size = s break } } if size == nil { t.Error("size not found") } if bytes.Compare(ec.calcECC(data, size), []byte{142, 164, 186, 114, 25, 5, 88, 102}) != 0 { t.Error("ECC Test 1 failed") } data = []byte{66, 129, 70} if bytes.Compare(ec.calcECC(data, size), []byte{66, 129, 70, 138, 234, 82, 82, 95}) != 0 { t.Error("ECC Test 2 failed") } } barcode-1.0.1/ean/000077500000000000000000000000001343272050500136545ustar00rootroot00000000000000barcode-1.0.1/ean/encoder.go000066400000000000000000000115241343272050500156250ustar00rootroot00000000000000// Package ean can create EAN 8 and EAN 13 barcodes. package ean import ( "errors" "github.com/boombuler/barcode" "github.com/boombuler/barcode/utils" ) type encodedNumber struct { LeftOdd []bool LeftEven []bool Right []bool CheckSum []bool } var encoderTable = map[rune]encodedNumber{ '0': encodedNumber{ []bool{false, false, false, true, true, false, true}, []bool{false, true, false, false, true, true, true}, []bool{true, true, true, false, false, true, false}, []bool{false, false, false, false, false, false}, }, '1': encodedNumber{ []bool{false, false, true, true, false, false, true}, []bool{false, true, true, false, false, true, true}, []bool{true, true, false, false, true, true, false}, []bool{false, false, true, false, true, true}, }, '2': encodedNumber{ []bool{false, false, true, false, false, true, true}, []bool{false, false, true, true, false, true, true}, []bool{true, true, false, true, true, false, false}, []bool{false, false, true, true, false, true}, }, '3': encodedNumber{ []bool{false, true, true, true, true, false, true}, []bool{false, true, false, false, false, false, true}, []bool{true, false, false, false, false, true, false}, []bool{false, false, true, true, true, false}, }, '4': encodedNumber{ []bool{false, true, false, false, false, true, true}, []bool{false, false, true, true, true, false, true}, []bool{true, false, true, true, true, false, false}, []bool{false, true, false, false, true, true}, }, '5': encodedNumber{ []bool{false, true, true, false, false, false, true}, []bool{false, true, true, true, false, false, true}, []bool{true, false, false, true, true, true, false}, []bool{false, true, true, false, false, true}, }, '6': encodedNumber{ []bool{false, true, false, true, true, true, true}, []bool{false, false, false, false, true, false, true}, []bool{true, false, true, false, false, false, false}, []bool{false, true, true, true, false, false}, }, '7': encodedNumber{ []bool{false, true, true, true, false, true, true}, []bool{false, false, true, false, false, false, true}, []bool{true, false, false, false, true, false, false}, []bool{false, true, false, true, false, true}, }, '8': encodedNumber{ []bool{false, true, true, false, true, true, true}, []bool{false, false, false, true, false, false, true}, []bool{true, false, false, true, false, false, false}, []bool{false, true, false, true, true, false}, }, '9': encodedNumber{ []bool{false, false, false, true, false, true, true}, []bool{false, false, true, false, true, true, true}, []bool{true, true, true, false, true, false, false}, []bool{false, true, true, false, true, false}, }, } func calcCheckNum(code string) rune { x3 := len(code) == 7 sum := 0 for _, r := range code { curNum := utils.RuneToInt(r) if curNum < 0 || curNum > 9 { return 'B' } if x3 { curNum = curNum * 3 } x3 = !x3 sum += curNum } return utils.IntToRune((10 - (sum % 10)) % 10) } func encodeEAN8(code string) *utils.BitList { result := new(utils.BitList) result.AddBit(true, false, true) for cpos, r := range code { num, ok := encoderTable[r] if !ok { return nil } var data []bool if cpos < 4 { data = num.LeftOdd } else { data = num.Right } if cpos == 4 { result.AddBit(false, true, false, true, false) } result.AddBit(data...) } result.AddBit(true, false, true) return result } func encodeEAN13(code string) *utils.BitList { result := new(utils.BitList) result.AddBit(true, false, true) var firstNum []bool for cpos, r := range code { num, ok := encoderTable[r] if !ok { return nil } if cpos == 0 { firstNum = num.CheckSum continue } var data []bool if cpos < 7 { // Left if firstNum[cpos-1] { data = num.LeftEven } else { data = num.LeftOdd } } else { data = num.Right } if cpos == 7 { result.AddBit(false, true, false, true, false) } result.AddBit(data...) } result.AddBit(true, false, true) return result } // Encode returns a EAN 8 or EAN 13 barcode for the given code func Encode(code string) (barcode.BarcodeIntCS, error) { var checkSum int if len(code) == 7 || len(code) == 12 { code += string(calcCheckNum(code)) checkSum = utils.RuneToInt(calcCheckNum(code)) } else if len(code) == 8 || len(code) == 13 { check := code[0 : len(code)-1] check += string(calcCheckNum(check)) if check != code { return nil, errors.New("checksum missmatch") } checkSum = utils.RuneToInt(rune(code[len(code)-1])) } if len(code) == 8 { result := encodeEAN8(code) if result != nil { return utils.New1DCodeIntCheckSum(barcode.TypeEAN8, code, result, checkSum), nil } } else if len(code) == 13 { result := encodeEAN13(code) if result != nil { return utils.New1DCodeIntCheckSum(barcode.TypeEAN13, code, result, checkSum), nil } } return nil, errors.New("invalid ean code data") } barcode-1.0.1/ean/encoder_test.go000066400000000000000000000025221343272050500166620ustar00rootroot00000000000000package ean import ( "image/color" "testing" ) func testHelper(t *testing.T, testCode, testResult, kind string, checkMetadata bool) { code, err := Encode(testCode) if err != nil { t.Error(err) } if checkMetadata && (code.Metadata().Dimensions != 1 || code.Content() != testCode || code.Metadata().CodeKind != kind) { t.Error("Metadata missmatch") } if len(testResult) != code.Bounds().Max.X { t.Fail() } for i, r := range testResult { if (code.At(i, 0) == color.Black) != (r == '1') { t.Fail() } } } func Test_EncodeEAN(t *testing.T) { testHelper(t, "5901234123457", "10100010110100111011001100100110111101001110101010110011011011001000010101110010011101000100101", "EAN 13", true) testHelper(t, "55123457", "1010110001011000100110010010011010101000010101110010011101000100101", "EAN 8", true) testHelper(t, "5512345", "1010110001011000100110010010011010101000010101110010011101000100101", "EAN 8", false) _, err := Encode("55123458") //<-- Invalid checksum if err == nil { t.Error("Invalid checksum not detected") } _, err = Encode("invalid") if err == nil { t.Error("\"invalid\" should not be encodable") } _, err = Encode("invalid") if err == nil { t.Error("\"invalid\" should not be encodable") } bits := encodeEAN13("invalid error") if bits != nil { t.Error("\"invalid error\" should not be encodable") } } barcode-1.0.1/go.mod000066400000000000000000000000441343272050500142150ustar00rootroot00000000000000module github.com/boombuler/barcode barcode-1.0.1/pdf417/000077500000000000000000000000001343272050500141165ustar00rootroot00000000000000barcode-1.0.1/pdf417/codewords.go000066400000000000000000000627601343272050500164510ustar00rootroot00000000000000package pdf417 const start_word = 0x1fea8 const stop_word = 0x3fa29 var codewords = [][]int{ []int{ 0x1d5c0, 0x1eaf0, 0x1f57c, 0x1d4e0, 0x1ea78, 0x1f53e, 0x1a8c0, 0x1d470, 0x1a860, 0x15040, 0x1a830, 0x15020, 0x1adc0, 0x1d6f0, 0x1eb7c, 0x1ace0, 0x1d678, 0x1eb3e, 0x158c0, 0x1ac70, 0x15860, 0x15dc0, 0x1aef0, 0x1d77c, 0x15ce0, 0x1ae78, 0x1d73e, 0x15c70, 0x1ae3c, 0x15ef0, 0x1af7c, 0x15e78, 0x1af3e, 0x15f7c, 0x1f5fa, 0x1d2e0, 0x1e978, 0x1f4be, 0x1a4c0, 0x1d270, 0x1e93c, 0x1a460, 0x1d238, 0x14840, 0x1a430, 0x1d21c, 0x14820, 0x1a418, 0x14810, 0x1a6e0, 0x1d378, 0x1e9be, 0x14cc0, 0x1a670, 0x1d33c, 0x14c60, 0x1a638, 0x1d31e, 0x14c30, 0x1a61c, 0x14ee0, 0x1a778, 0x1d3be, 0x14e70, 0x1a73c, 0x14e38, 0x1a71e, 0x14f78, 0x1a7be, 0x14f3c, 0x14f1e, 0x1a2c0, 0x1d170, 0x1e8bc, 0x1a260, 0x1d138, 0x1e89e, 0x14440, 0x1a230, 0x1d11c, 0x14420, 0x1a218, 0x14410, 0x14408, 0x146c0, 0x1a370, 0x1d1bc, 0x14660, 0x1a338, 0x1d19e, 0x14630, 0x1a31c, 0x14618, 0x1460c, 0x14770, 0x1a3bc, 0x14738, 0x1a39e, 0x1471c, 0x147bc, 0x1a160, 0x1d0b8, 0x1e85e, 0x14240, 0x1a130, 0x1d09c, 0x14220, 0x1a118, 0x1d08e, 0x14210, 0x1a10c, 0x14208, 0x1a106, 0x14360, 0x1a1b8, 0x1d0de, 0x14330, 0x1a19c, 0x14318, 0x1a18e, 0x1430c, 0x14306, 0x1a1de, 0x1438e, 0x14140, 0x1a0b0, 0x1d05c, 0x14120, 0x1a098, 0x1d04e, 0x14110, 0x1a08c, 0x14108, 0x1a086, 0x14104, 0x141b0, 0x14198, 0x1418c, 0x140a0, 0x1d02e, 0x1a04c, 0x1a046, 0x14082, 0x1cae0, 0x1e578, 0x1f2be, 0x194c0, 0x1ca70, 0x1e53c, 0x19460, 0x1ca38, 0x1e51e, 0x12840, 0x19430, 0x12820, 0x196e0, 0x1cb78, 0x1e5be, 0x12cc0, 0x19670, 0x1cb3c, 0x12c60, 0x19638, 0x12c30, 0x12c18, 0x12ee0, 0x19778, 0x1cbbe, 0x12e70, 0x1973c, 0x12e38, 0x12e1c, 0x12f78, 0x197be, 0x12f3c, 0x12fbe, 0x1dac0, 0x1ed70, 0x1f6bc, 0x1da60, 0x1ed38, 0x1f69e, 0x1b440, 0x1da30, 0x1ed1c, 0x1b420, 0x1da18, 0x1ed0e, 0x1b410, 0x1da0c, 0x192c0, 0x1c970, 0x1e4bc, 0x1b6c0, 0x19260, 0x1c938, 0x1e49e, 0x1b660, 0x1db38, 0x1ed9e, 0x16c40, 0x12420, 0x19218, 0x1c90e, 0x16c20, 0x1b618, 0x16c10, 0x126c0, 0x19370, 0x1c9bc, 0x16ec0, 0x12660, 0x19338, 0x1c99e, 0x16e60, 0x1b738, 0x1db9e, 0x16e30, 0x12618, 0x16e18, 0x12770, 0x193bc, 0x16f70, 0x12738, 0x1939e, 0x16f38, 0x1b79e, 0x16f1c, 0x127bc, 0x16fbc, 0x1279e, 0x16f9e, 0x1d960, 0x1ecb8, 0x1f65e, 0x1b240, 0x1d930, 0x1ec9c, 0x1b220, 0x1d918, 0x1ec8e, 0x1b210, 0x1d90c, 0x1b208, 0x1b204, 0x19160, 0x1c8b8, 0x1e45e, 0x1b360, 0x19130, 0x1c89c, 0x16640, 0x12220, 0x1d99c, 0x1c88e, 0x16620, 0x12210, 0x1910c, 0x16610, 0x1b30c, 0x19106, 0x12204, 0x12360, 0x191b8, 0x1c8de, 0x16760, 0x12330, 0x1919c, 0x16730, 0x1b39c, 0x1918e, 0x16718, 0x1230c, 0x12306, 0x123b8, 0x191de, 0x167b8, 0x1239c, 0x1679c, 0x1238e, 0x1678e, 0x167de, 0x1b140, 0x1d8b0, 0x1ec5c, 0x1b120, 0x1d898, 0x1ec4e, 0x1b110, 0x1d88c, 0x1b108, 0x1d886, 0x1b104, 0x1b102, 0x12140, 0x190b0, 0x1c85c, 0x16340, 0x12120, 0x19098, 0x1c84e, 0x16320, 0x1b198, 0x1d8ce, 0x16310, 0x12108, 0x19086, 0x16308, 0x1b186, 0x16304, 0x121b0, 0x190dc, 0x163b0, 0x12198, 0x190ce, 0x16398, 0x1b1ce, 0x1638c, 0x12186, 0x16386, 0x163dc, 0x163ce, 0x1b0a0, 0x1d858, 0x1ec2e, 0x1b090, 0x1d84c, 0x1b088, 0x1d846, 0x1b084, 0x1b082, 0x120a0, 0x19058, 0x1c82e, 0x161a0, 0x12090, 0x1904c, 0x16190, 0x1b0cc, 0x19046, 0x16188, 0x12084, 0x16184, 0x12082, 0x120d8, 0x161d8, 0x161cc, 0x161c6, 0x1d82c, 0x1d826, 0x1b042, 0x1902c, 0x12048, 0x160c8, 0x160c4, 0x160c2, 0x18ac0, 0x1c570, 0x1e2bc, 0x18a60, 0x1c538, 0x11440, 0x18a30, 0x1c51c, 0x11420, 0x18a18, 0x11410, 0x11408, 0x116c0, 0x18b70, 0x1c5bc, 0x11660, 0x18b38, 0x1c59e, 0x11630, 0x18b1c, 0x11618, 0x1160c, 0x11770, 0x18bbc, 0x11738, 0x18b9e, 0x1171c, 0x117bc, 0x1179e, 0x1cd60, 0x1e6b8, 0x1f35e, 0x19a40, 0x1cd30, 0x1e69c, 0x19a20, 0x1cd18, 0x1e68e, 0x19a10, 0x1cd0c, 0x19a08, 0x1cd06, 0x18960, 0x1c4b8, 0x1e25e, 0x19b60, 0x18930, 0x1c49c, 0x13640, 0x11220, 0x1cd9c, 0x1c48e, 0x13620, 0x19b18, 0x1890c, 0x13610, 0x11208, 0x13608, 0x11360, 0x189b8, 0x1c4de, 0x13760, 0x11330, 0x1cdde, 0x13730, 0x19b9c, 0x1898e, 0x13718, 0x1130c, 0x1370c, 0x113b8, 0x189de, 0x137b8, 0x1139c, 0x1379c, 0x1138e, 0x113de, 0x137de, 0x1dd40, 0x1eeb0, 0x1f75c, 0x1dd20, 0x1ee98, 0x1f74e, 0x1dd10, 0x1ee8c, 0x1dd08, 0x1ee86, 0x1dd04, 0x19940, 0x1ccb0, 0x1e65c, 0x1bb40, 0x19920, 0x1eedc, 0x1e64e, 0x1bb20, 0x1dd98, 0x1eece, 0x1bb10, 0x19908, 0x1cc86, 0x1bb08, 0x1dd86, 0x19902, 0x11140, 0x188b0, 0x1c45c, 0x13340, 0x11120, 0x18898, 0x1c44e, 0x17740, 0x13320, 0x19998, 0x1ccce, 0x17720, 0x1bb98, 0x1ddce, 0x18886, 0x17710, 0x13308, 0x19986, 0x17708, 0x11102, 0x111b0, 0x188dc, 0x133b0, 0x11198, 0x188ce, 0x177b0, 0x13398, 0x199ce, 0x17798, 0x1bbce, 0x11186, 0x13386, 0x111dc, 0x133dc, 0x111ce, 0x177dc, 0x133ce, 0x1dca0, 0x1ee58, 0x1f72e, 0x1dc90, 0x1ee4c, 0x1dc88, 0x1ee46, 0x1dc84, 0x1dc82, 0x198a0, 0x1cc58, 0x1e62e, 0x1b9a0, 0x19890, 0x1ee6e, 0x1b990, 0x1dccc, 0x1cc46, 0x1b988, 0x19884, 0x1b984, 0x19882, 0x1b982, 0x110a0, 0x18858, 0x1c42e, 0x131a0, 0x11090, 0x1884c, 0x173a0, 0x13190, 0x198cc, 0x18846, 0x17390, 0x1b9cc, 0x11084, 0x17388, 0x13184, 0x11082, 0x13182, 0x110d8, 0x1886e, 0x131d8, 0x110cc, 0x173d8, 0x131cc, 0x110c6, 0x173cc, 0x131c6, 0x110ee, 0x173ee, 0x1dc50, 0x1ee2c, 0x1dc48, 0x1ee26, 0x1dc44, 0x1dc42, 0x19850, 0x1cc2c, 0x1b8d0, 0x19848, 0x1cc26, 0x1b8c8, 0x1dc66, 0x1b8c4, 0x19842, 0x1b8c2, 0x11050, 0x1882c, 0x130d0, 0x11048, 0x18826, 0x171d0, 0x130c8, 0x19866, 0x171c8, 0x1b8e6, 0x11042, 0x171c4, 0x130c2, 0x171c2, 0x130ec, 0x171ec, 0x171e6, 0x1ee16, 0x1dc22, 0x1cc16, 0x19824, 0x19822, 0x11028, 0x13068, 0x170e8, 0x11022, 0x13062, 0x18560, 0x10a40, 0x18530, 0x10a20, 0x18518, 0x1c28e, 0x10a10, 0x1850c, 0x10a08, 0x18506, 0x10b60, 0x185b8, 0x1c2de, 0x10b30, 0x1859c, 0x10b18, 0x1858e, 0x10b0c, 0x10b06, 0x10bb8, 0x185de, 0x10b9c, 0x10b8e, 0x10bde, 0x18d40, 0x1c6b0, 0x1e35c, 0x18d20, 0x1c698, 0x18d10, 0x1c68c, 0x18d08, 0x1c686, 0x18d04, 0x10940, 0x184b0, 0x1c25c, 0x11b40, 0x10920, 0x1c6dc, 0x1c24e, 0x11b20, 0x18d98, 0x1c6ce, 0x11b10, 0x10908, 0x18486, 0x11b08, 0x18d86, 0x10902, 0x109b0, 0x184dc, 0x11bb0, 0x10998, 0x184ce, 0x11b98, 0x18dce, 0x11b8c, 0x10986, 0x109dc, 0x11bdc, 0x109ce, 0x11bce, 0x1cea0, 0x1e758, 0x1f3ae, 0x1ce90, 0x1e74c, 0x1ce88, 0x1e746, 0x1ce84, 0x1ce82, 0x18ca0, 0x1c658, 0x19da0, 0x18c90, 0x1c64c, 0x19d90, 0x1cecc, 0x1c646, 0x19d88, 0x18c84, 0x19d84, 0x18c82, 0x19d82, 0x108a0, 0x18458, 0x119a0, 0x10890, 0x1c66e, 0x13ba0, 0x11990, 0x18ccc, 0x18446, 0x13b90, 0x19dcc, 0x10884, 0x13b88, 0x11984, 0x10882, 0x11982, 0x108d8, 0x1846e, 0x119d8, 0x108cc, 0x13bd8, 0x119cc, 0x108c6, 0x13bcc, 0x119c6, 0x108ee, 0x119ee, 0x13bee, 0x1ef50, 0x1f7ac, 0x1ef48, 0x1f7a6, 0x1ef44, 0x1ef42, 0x1ce50, 0x1e72c, 0x1ded0, 0x1ef6c, 0x1e726, 0x1dec8, 0x1ef66, 0x1dec4, 0x1ce42, 0x1dec2, 0x18c50, 0x1c62c, 0x19cd0, 0x18c48, 0x1c626, 0x1bdd0, 0x19cc8, 0x1ce66, 0x1bdc8, 0x1dee6, 0x18c42, 0x1bdc4, 0x19cc2, 0x1bdc2, 0x10850, 0x1842c, 0x118d0, 0x10848, 0x18426, 0x139d0, 0x118c8, 0x18c66, 0x17bd0, 0x139c8, 0x19ce6, 0x10842, 0x17bc8, 0x1bde6, 0x118c2, 0x17bc4, 0x1086c, 0x118ec, 0x10866, 0x139ec, 0x118e6, 0x17bec, 0x139e6, 0x17be6, 0x1ef28, 0x1f796, 0x1ef24, 0x1ef22, 0x1ce28, 0x1e716, 0x1de68, 0x1ef36, 0x1de64, 0x1ce22, 0x1de62, 0x18c28, 0x1c616, 0x19c68, 0x18c24, 0x1bce8, 0x19c64, 0x18c22, 0x1bce4, 0x19c62, 0x1bce2, 0x10828, 0x18416, 0x11868, 0x18c36, 0x138e8, 0x11864, 0x10822, 0x179e8, 0x138e4, 0x11862, 0x179e4, 0x138e2, 0x179e2, 0x11876, 0x179f6, 0x1ef12, 0x1de34, 0x1de32, 0x19c34, 0x1bc74, 0x1bc72, 0x11834, 0x13874, 0x178f4, 0x178f2, 0x10540, 0x10520, 0x18298, 0x10510, 0x10508, 0x10504, 0x105b0, 0x10598, 0x1058c, 0x10586, 0x105dc, 0x105ce, 0x186a0, 0x18690, 0x1c34c, 0x18688, 0x1c346, 0x18684, 0x18682, 0x104a0, 0x18258, 0x10da0, 0x186d8, 0x1824c, 0x10d90, 0x186cc, 0x10d88, 0x186c6, 0x10d84, 0x10482, 0x10d82, 0x104d8, 0x1826e, 0x10dd8, 0x186ee, 0x10dcc, 0x104c6, 0x10dc6, 0x104ee, 0x10dee, 0x1c750, 0x1c748, 0x1c744, 0x1c742, 0x18650, 0x18ed0, 0x1c76c, 0x1c326, 0x18ec8, 0x1c766, 0x18ec4, 0x18642, 0x18ec2, 0x10450, 0x10cd0, 0x10448, 0x18226, 0x11dd0, 0x10cc8, 0x10444, 0x11dc8, 0x10cc4, 0x10442, 0x11dc4, 0x10cc2, 0x1046c, 0x10cec, 0x10466, 0x11dec, 0x10ce6, 0x11de6, 0x1e7a8, 0x1e7a4, 0x1e7a2, 0x1c728, 0x1cf68, 0x1e7b6, 0x1cf64, 0x1c722, 0x1cf62, 0x18628, 0x1c316, 0x18e68, 0x1c736, 0x19ee8, 0x18e64, 0x18622, 0x19ee4, 0x18e62, 0x19ee2, 0x10428, 0x18216, 0x10c68, 0x18636, 0x11ce8, 0x10c64, 0x10422, 0x13de8, 0x11ce4, 0x10c62, 0x13de4, 0x11ce2, 0x10436, 0x10c76, 0x11cf6, 0x13df6, 0x1f7d4, 0x1f7d2, 0x1e794, 0x1efb4, 0x1e792, 0x1efb2, 0x1c714, 0x1cf34, 0x1c712, 0x1df74, 0x1cf32, 0x1df72, 0x18614, 0x18e34, 0x18612, 0x19e74, 0x18e32, 0x1bef4, }, []int{ 0x1f560, 0x1fab8, 0x1ea40, 0x1f530, 0x1fa9c, 0x1ea20, 0x1f518, 0x1fa8e, 0x1ea10, 0x1f50c, 0x1ea08, 0x1f506, 0x1ea04, 0x1eb60, 0x1f5b8, 0x1fade, 0x1d640, 0x1eb30, 0x1f59c, 0x1d620, 0x1eb18, 0x1f58e, 0x1d610, 0x1eb0c, 0x1d608, 0x1eb06, 0x1d604, 0x1d760, 0x1ebb8, 0x1f5de, 0x1ae40, 0x1d730, 0x1eb9c, 0x1ae20, 0x1d718, 0x1eb8e, 0x1ae10, 0x1d70c, 0x1ae08, 0x1d706, 0x1ae04, 0x1af60, 0x1d7b8, 0x1ebde, 0x15e40, 0x1af30, 0x1d79c, 0x15e20, 0x1af18, 0x1d78e, 0x15e10, 0x1af0c, 0x15e08, 0x1af06, 0x15f60, 0x1afb8, 0x1d7de, 0x15f30, 0x1af9c, 0x15f18, 0x1af8e, 0x15f0c, 0x15fb8, 0x1afde, 0x15f9c, 0x15f8e, 0x1e940, 0x1f4b0, 0x1fa5c, 0x1e920, 0x1f498, 0x1fa4e, 0x1e910, 0x1f48c, 0x1e908, 0x1f486, 0x1e904, 0x1e902, 0x1d340, 0x1e9b0, 0x1f4dc, 0x1d320, 0x1e998, 0x1f4ce, 0x1d310, 0x1e98c, 0x1d308, 0x1e986, 0x1d304, 0x1d302, 0x1a740, 0x1d3b0, 0x1e9dc, 0x1a720, 0x1d398, 0x1e9ce, 0x1a710, 0x1d38c, 0x1a708, 0x1d386, 0x1a704, 0x1a702, 0x14f40, 0x1a7b0, 0x1d3dc, 0x14f20, 0x1a798, 0x1d3ce, 0x14f10, 0x1a78c, 0x14f08, 0x1a786, 0x14f04, 0x14fb0, 0x1a7dc, 0x14f98, 0x1a7ce, 0x14f8c, 0x14f86, 0x14fdc, 0x14fce, 0x1e8a0, 0x1f458, 0x1fa2e, 0x1e890, 0x1f44c, 0x1e888, 0x1f446, 0x1e884, 0x1e882, 0x1d1a0, 0x1e8d8, 0x1f46e, 0x1d190, 0x1e8cc, 0x1d188, 0x1e8c6, 0x1d184, 0x1d182, 0x1a3a0, 0x1d1d8, 0x1e8ee, 0x1a390, 0x1d1cc, 0x1a388, 0x1d1c6, 0x1a384, 0x1a382, 0x147a0, 0x1a3d8, 0x1d1ee, 0x14790, 0x1a3cc, 0x14788, 0x1a3c6, 0x14784, 0x14782, 0x147d8, 0x1a3ee, 0x147cc, 0x147c6, 0x147ee, 0x1e850, 0x1f42c, 0x1e848, 0x1f426, 0x1e844, 0x1e842, 0x1d0d0, 0x1e86c, 0x1d0c8, 0x1e866, 0x1d0c4, 0x1d0c2, 0x1a1d0, 0x1d0ec, 0x1a1c8, 0x1d0e6, 0x1a1c4, 0x1a1c2, 0x143d0, 0x1a1ec, 0x143c8, 0x1a1e6, 0x143c4, 0x143c2, 0x143ec, 0x143e6, 0x1e828, 0x1f416, 0x1e824, 0x1e822, 0x1d068, 0x1e836, 0x1d064, 0x1d062, 0x1a0e8, 0x1d076, 0x1a0e4, 0x1a0e2, 0x141e8, 0x1a0f6, 0x141e4, 0x141e2, 0x1e814, 0x1e812, 0x1d034, 0x1d032, 0x1a074, 0x1a072, 0x1e540, 0x1f2b0, 0x1f95c, 0x1e520, 0x1f298, 0x1f94e, 0x1e510, 0x1f28c, 0x1e508, 0x1f286, 0x1e504, 0x1e502, 0x1cb40, 0x1e5b0, 0x1f2dc, 0x1cb20, 0x1e598, 0x1f2ce, 0x1cb10, 0x1e58c, 0x1cb08, 0x1e586, 0x1cb04, 0x1cb02, 0x19740, 0x1cbb0, 0x1e5dc, 0x19720, 0x1cb98, 0x1e5ce, 0x19710, 0x1cb8c, 0x19708, 0x1cb86, 0x19704, 0x19702, 0x12f40, 0x197b0, 0x1cbdc, 0x12f20, 0x19798, 0x1cbce, 0x12f10, 0x1978c, 0x12f08, 0x19786, 0x12f04, 0x12fb0, 0x197dc, 0x12f98, 0x197ce, 0x12f8c, 0x12f86, 0x12fdc, 0x12fce, 0x1f6a0, 0x1fb58, 0x16bf0, 0x1f690, 0x1fb4c, 0x169f8, 0x1f688, 0x1fb46, 0x168fc, 0x1f684, 0x1f682, 0x1e4a0, 0x1f258, 0x1f92e, 0x1eda0, 0x1e490, 0x1fb6e, 0x1ed90, 0x1f6cc, 0x1f246, 0x1ed88, 0x1e484, 0x1ed84, 0x1e482, 0x1ed82, 0x1c9a0, 0x1e4d8, 0x1f26e, 0x1dba0, 0x1c990, 0x1e4cc, 0x1db90, 0x1edcc, 0x1e4c6, 0x1db88, 0x1c984, 0x1db84, 0x1c982, 0x1db82, 0x193a0, 0x1c9d8, 0x1e4ee, 0x1b7a0, 0x19390, 0x1c9cc, 0x1b790, 0x1dbcc, 0x1c9c6, 0x1b788, 0x19384, 0x1b784, 0x19382, 0x1b782, 0x127a0, 0x193d8, 0x1c9ee, 0x16fa0, 0x12790, 0x193cc, 0x16f90, 0x1b7cc, 0x193c6, 0x16f88, 0x12784, 0x16f84, 0x12782, 0x127d8, 0x193ee, 0x16fd8, 0x127cc, 0x16fcc, 0x127c6, 0x16fc6, 0x127ee, 0x1f650, 0x1fb2c, 0x165f8, 0x1f648, 0x1fb26, 0x164fc, 0x1f644, 0x1647e, 0x1f642, 0x1e450, 0x1f22c, 0x1ecd0, 0x1e448, 0x1f226, 0x1ecc8, 0x1f666, 0x1ecc4, 0x1e442, 0x1ecc2, 0x1c8d0, 0x1e46c, 0x1d9d0, 0x1c8c8, 0x1e466, 0x1d9c8, 0x1ece6, 0x1d9c4, 0x1c8c2, 0x1d9c2, 0x191d0, 0x1c8ec, 0x1b3d0, 0x191c8, 0x1c8e6, 0x1b3c8, 0x1d9e6, 0x1b3c4, 0x191c2, 0x1b3c2, 0x123d0, 0x191ec, 0x167d0, 0x123c8, 0x191e6, 0x167c8, 0x1b3e6, 0x167c4, 0x123c2, 0x167c2, 0x123ec, 0x167ec, 0x123e6, 0x167e6, 0x1f628, 0x1fb16, 0x162fc, 0x1f624, 0x1627e, 0x1f622, 0x1e428, 0x1f216, 0x1ec68, 0x1f636, 0x1ec64, 0x1e422, 0x1ec62, 0x1c868, 0x1e436, 0x1d8e8, 0x1c864, 0x1d8e4, 0x1c862, 0x1d8e2, 0x190e8, 0x1c876, 0x1b1e8, 0x1d8f6, 0x1b1e4, 0x190e2, 0x1b1e2, 0x121e8, 0x190f6, 0x163e8, 0x121e4, 0x163e4, 0x121e2, 0x163e2, 0x121f6, 0x163f6, 0x1f614, 0x1617e, 0x1f612, 0x1e414, 0x1ec34, 0x1e412, 0x1ec32, 0x1c834, 0x1d874, 0x1c832, 0x1d872, 0x19074, 0x1b0f4, 0x19072, 0x1b0f2, 0x120f4, 0x161f4, 0x120f2, 0x161f2, 0x1f60a, 0x1e40a, 0x1ec1a, 0x1c81a, 0x1d83a, 0x1903a, 0x1b07a, 0x1e2a0, 0x1f158, 0x1f8ae, 0x1e290, 0x1f14c, 0x1e288, 0x1f146, 0x1e284, 0x1e282, 0x1c5a0, 0x1e2d8, 0x1f16e, 0x1c590, 0x1e2cc, 0x1c588, 0x1e2c6, 0x1c584, 0x1c582, 0x18ba0, 0x1c5d8, 0x1e2ee, 0x18b90, 0x1c5cc, 0x18b88, 0x1c5c6, 0x18b84, 0x18b82, 0x117a0, 0x18bd8, 0x1c5ee, 0x11790, 0x18bcc, 0x11788, 0x18bc6, 0x11784, 0x11782, 0x117d8, 0x18bee, 0x117cc, 0x117c6, 0x117ee, 0x1f350, 0x1f9ac, 0x135f8, 0x1f348, 0x1f9a6, 0x134fc, 0x1f344, 0x1347e, 0x1f342, 0x1e250, 0x1f12c, 0x1e6d0, 0x1e248, 0x1f126, 0x1e6c8, 0x1f366, 0x1e6c4, 0x1e242, 0x1e6c2, 0x1c4d0, 0x1e26c, 0x1cdd0, 0x1c4c8, 0x1e266, 0x1cdc8, 0x1e6e6, 0x1cdc4, 0x1c4c2, 0x1cdc2, 0x189d0, 0x1c4ec, 0x19bd0, 0x189c8, 0x1c4e6, 0x19bc8, 0x1cde6, 0x19bc4, 0x189c2, 0x19bc2, 0x113d0, 0x189ec, 0x137d0, 0x113c8, 0x189e6, 0x137c8, 0x19be6, 0x137c4, 0x113c2, 0x137c2, 0x113ec, 0x137ec, 0x113e6, 0x137e6, 0x1fba8, 0x175f0, 0x1bafc, 0x1fba4, 0x174f8, 0x1ba7e, 0x1fba2, 0x1747c, 0x1743e, 0x1f328, 0x1f996, 0x132fc, 0x1f768, 0x1fbb6, 0x176fc, 0x1327e, 0x1f764, 0x1f322, 0x1767e, 0x1f762, 0x1e228, 0x1f116, 0x1e668, 0x1e224, 0x1eee8, 0x1f776, 0x1e222, 0x1eee4, 0x1e662, 0x1eee2, 0x1c468, 0x1e236, 0x1cce8, 0x1c464, 0x1dde8, 0x1cce4, 0x1c462, 0x1dde4, 0x1cce2, 0x1dde2, 0x188e8, 0x1c476, 0x199e8, 0x188e4, 0x1bbe8, 0x199e4, 0x188e2, 0x1bbe4, 0x199e2, 0x1bbe2, 0x111e8, 0x188f6, 0x133e8, 0x111e4, 0x177e8, 0x133e4, 0x111e2, 0x177e4, 0x133e2, 0x177e2, 0x111f6, 0x133f6, 0x1fb94, 0x172f8, 0x1b97e, 0x1fb92, 0x1727c, 0x1723e, 0x1f314, 0x1317e, 0x1f734, 0x1f312, 0x1737e, 0x1f732, 0x1e214, 0x1e634, 0x1e212, 0x1ee74, 0x1e632, 0x1ee72, 0x1c434, 0x1cc74, 0x1c432, 0x1dcf4, 0x1cc72, 0x1dcf2, 0x18874, 0x198f4, 0x18872, 0x1b9f4, 0x198f2, 0x1b9f2, 0x110f4, 0x131f4, 0x110f2, 0x173f4, 0x131f2, 0x173f2, 0x1fb8a, 0x1717c, 0x1713e, 0x1f30a, 0x1f71a, 0x1e20a, 0x1e61a, 0x1ee3a, 0x1c41a, 0x1cc3a, 0x1dc7a, 0x1883a, 0x1987a, 0x1b8fa, 0x1107a, 0x130fa, 0x171fa, 0x170be, 0x1e150, 0x1f0ac, 0x1e148, 0x1f0a6, 0x1e144, 0x1e142, 0x1c2d0, 0x1e16c, 0x1c2c8, 0x1e166, 0x1c2c4, 0x1c2c2, 0x185d0, 0x1c2ec, 0x185c8, 0x1c2e6, 0x185c4, 0x185c2, 0x10bd0, 0x185ec, 0x10bc8, 0x185e6, 0x10bc4, 0x10bc2, 0x10bec, 0x10be6, 0x1f1a8, 0x1f8d6, 0x11afc, 0x1f1a4, 0x11a7e, 0x1f1a2, 0x1e128, 0x1f096, 0x1e368, 0x1e124, 0x1e364, 0x1e122, 0x1e362, 0x1c268, 0x1e136, 0x1c6e8, 0x1c264, 0x1c6e4, 0x1c262, 0x1c6e2, 0x184e8, 0x1c276, 0x18de8, 0x184e4, 0x18de4, 0x184e2, 0x18de2, 0x109e8, 0x184f6, 0x11be8, 0x109e4, 0x11be4, 0x109e2, 0x11be2, 0x109f6, 0x11bf6, 0x1f9d4, 0x13af8, 0x19d7e, 0x1f9d2, 0x13a7c, 0x13a3e, 0x1f194, 0x1197e, 0x1f3b4, 0x1f192, 0x13b7e, 0x1f3b2, 0x1e114, 0x1e334, 0x1e112, 0x1e774, 0x1e332, 0x1e772, 0x1c234, 0x1c674, 0x1c232, 0x1cef4, 0x1c672, 0x1cef2, 0x18474, 0x18cf4, 0x18472, 0x19df4, 0x18cf2, 0x19df2, 0x108f4, 0x119f4, 0x108f2, 0x13bf4, 0x119f2, 0x13bf2, 0x17af0, 0x1bd7c, 0x17a78, 0x1bd3e, 0x17a3c, 0x17a1e, 0x1f9ca, 0x1397c, 0x1fbda, 0x17b7c, 0x1393e, 0x17b3e, 0x1f18a, 0x1f39a, 0x1f7ba, 0x1e10a, 0x1e31a, 0x1e73a, 0x1ef7a, 0x1c21a, 0x1c63a, 0x1ce7a, 0x1defa, 0x1843a, 0x18c7a, 0x19cfa, 0x1bdfa, 0x1087a, 0x118fa, 0x139fa, 0x17978, 0x1bcbe, 0x1793c, 0x1791e, 0x138be, 0x179be, 0x178bc, 0x1789e, 0x1785e, 0x1e0a8, 0x1e0a4, 0x1e0a2, 0x1c168, 0x1e0b6, 0x1c164, 0x1c162, 0x182e8, 0x1c176, 0x182e4, 0x182e2, 0x105e8, 0x182f6, 0x105e4, 0x105e2, 0x105f6, 0x1f0d4, 0x10d7e, 0x1f0d2, 0x1e094, 0x1e1b4, 0x1e092, 0x1e1b2, 0x1c134, 0x1c374, 0x1c132, 0x1c372, 0x18274, 0x186f4, 0x18272, 0x186f2, 0x104f4, 0x10df4, 0x104f2, 0x10df2, 0x1f8ea, 0x11d7c, 0x11d3e, 0x1f0ca, 0x1f1da, 0x1e08a, 0x1e19a, 0x1e3ba, 0x1c11a, 0x1c33a, 0x1c77a, 0x1823a, 0x1867a, 0x18efa, 0x1047a, 0x10cfa, 0x11dfa, 0x13d78, 0x19ebe, 0x13d3c, 0x13d1e, 0x11cbe, 0x13dbe, 0x17d70, 0x1bebc, 0x17d38, 0x1be9e, 0x17d1c, 0x17d0e, 0x13cbc, 0x17dbc, 0x13c9e, 0x17d9e, 0x17cb8, 0x1be5e, 0x17c9c, 0x17c8e, 0x13c5e, 0x17cde, 0x17c5c, 0x17c4e, 0x17c2e, 0x1c0b4, 0x1c0b2, 0x18174, 0x18172, 0x102f4, 0x102f2, 0x1e0da, 0x1c09a, 0x1c1ba, 0x1813a, 0x1837a, 0x1027a, 0x106fa, 0x10ebe, 0x11ebc, 0x11e9e, 0x13eb8, 0x19f5e, 0x13e9c, 0x13e8e, 0x11e5e, 0x13ede, 0x17eb0, 0x1bf5c, 0x17e98, 0x1bf4e, 0x17e8c, 0x17e86, 0x13e5c, 0x17edc, 0x13e4e, 0x17ece, 0x17e58, 0x1bf2e, 0x17e4c, 0x17e46, 0x13e2e, 0x17e6e, 0x17e2c, 0x17e26, 0x10f5e, 0x11f5c, 0x11f4e, 0x13f58, 0x19fae, 0x13f4c, 0x13f46, 0x11f2e, 0x13f6e, 0x13f2c, 0x13f26, }, []int{ 0x1abe0, 0x1d5f8, 0x153c0, 0x1a9f0, 0x1d4fc, 0x151e0, 0x1a8f8, 0x1d47e, 0x150f0, 0x1a87c, 0x15078, 0x1fad0, 0x15be0, 0x1adf8, 0x1fac8, 0x159f0, 0x1acfc, 0x1fac4, 0x158f8, 0x1ac7e, 0x1fac2, 0x1587c, 0x1f5d0, 0x1faec, 0x15df8, 0x1f5c8, 0x1fae6, 0x15cfc, 0x1f5c4, 0x15c7e, 0x1f5c2, 0x1ebd0, 0x1f5ec, 0x1ebc8, 0x1f5e6, 0x1ebc4, 0x1ebc2, 0x1d7d0, 0x1ebec, 0x1d7c8, 0x1ebe6, 0x1d7c4, 0x1d7c2, 0x1afd0, 0x1d7ec, 0x1afc8, 0x1d7e6, 0x1afc4, 0x14bc0, 0x1a5f0, 0x1d2fc, 0x149e0, 0x1a4f8, 0x1d27e, 0x148f0, 0x1a47c, 0x14878, 0x1a43e, 0x1483c, 0x1fa68, 0x14df0, 0x1a6fc, 0x1fa64, 0x14cf8, 0x1a67e, 0x1fa62, 0x14c7c, 0x14c3e, 0x1f4e8, 0x1fa76, 0x14efc, 0x1f4e4, 0x14e7e, 0x1f4e2, 0x1e9e8, 0x1f4f6, 0x1e9e4, 0x1e9e2, 0x1d3e8, 0x1e9f6, 0x1d3e4, 0x1d3e2, 0x1a7e8, 0x1d3f6, 0x1a7e4, 0x1a7e2, 0x145e0, 0x1a2f8, 0x1d17e, 0x144f0, 0x1a27c, 0x14478, 0x1a23e, 0x1443c, 0x1441e, 0x1fa34, 0x146f8, 0x1a37e, 0x1fa32, 0x1467c, 0x1463e, 0x1f474, 0x1477e, 0x1f472, 0x1e8f4, 0x1e8f2, 0x1d1f4, 0x1d1f2, 0x1a3f4, 0x1a3f2, 0x142f0, 0x1a17c, 0x14278, 0x1a13e, 0x1423c, 0x1421e, 0x1fa1a, 0x1437c, 0x1433e, 0x1f43a, 0x1e87a, 0x1d0fa, 0x14178, 0x1a0be, 0x1413c, 0x1411e, 0x141be, 0x140bc, 0x1409e, 0x12bc0, 0x195f0, 0x1cafc, 0x129e0, 0x194f8, 0x1ca7e, 0x128f0, 0x1947c, 0x12878, 0x1943e, 0x1283c, 0x1f968, 0x12df0, 0x196fc, 0x1f964, 0x12cf8, 0x1967e, 0x1f962, 0x12c7c, 0x12c3e, 0x1f2e8, 0x1f976, 0x12efc, 0x1f2e4, 0x12e7e, 0x1f2e2, 0x1e5e8, 0x1f2f6, 0x1e5e4, 0x1e5e2, 0x1cbe8, 0x1e5f6, 0x1cbe4, 0x1cbe2, 0x197e8, 0x1cbf6, 0x197e4, 0x197e2, 0x1b5e0, 0x1daf8, 0x1ed7e, 0x169c0, 0x1b4f0, 0x1da7c, 0x168e0, 0x1b478, 0x1da3e, 0x16870, 0x1b43c, 0x16838, 0x1b41e, 0x1681c, 0x125e0, 0x192f8, 0x1c97e, 0x16de0, 0x124f0, 0x1927c, 0x16cf0, 0x1b67c, 0x1923e, 0x16c78, 0x1243c, 0x16c3c, 0x1241e, 0x16c1e, 0x1f934, 0x126f8, 0x1937e, 0x1fb74, 0x1f932, 0x16ef8, 0x1267c, 0x1fb72, 0x16e7c, 0x1263e, 0x16e3e, 0x1f274, 0x1277e, 0x1f6f4, 0x1f272, 0x16f7e, 0x1f6f2, 0x1e4f4, 0x1edf4, 0x1e4f2, 0x1edf2, 0x1c9f4, 0x1dbf4, 0x1c9f2, 0x1dbf2, 0x193f4, 0x193f2, 0x165c0, 0x1b2f0, 0x1d97c, 0x164e0, 0x1b278, 0x1d93e, 0x16470, 0x1b23c, 0x16438, 0x1b21e, 0x1641c, 0x1640e, 0x122f0, 0x1917c, 0x166f0, 0x12278, 0x1913e, 0x16678, 0x1b33e, 0x1663c, 0x1221e, 0x1661e, 0x1f91a, 0x1237c, 0x1fb3a, 0x1677c, 0x1233e, 0x1673e, 0x1f23a, 0x1f67a, 0x1e47a, 0x1ecfa, 0x1c8fa, 0x1d9fa, 0x191fa, 0x162e0, 0x1b178, 0x1d8be, 0x16270, 0x1b13c, 0x16238, 0x1b11e, 0x1621c, 0x1620e, 0x12178, 0x190be, 0x16378, 0x1213c, 0x1633c, 0x1211e, 0x1631e, 0x121be, 0x163be, 0x16170, 0x1b0bc, 0x16138, 0x1b09e, 0x1611c, 0x1610e, 0x120bc, 0x161bc, 0x1209e, 0x1619e, 0x160b8, 0x1b05e, 0x1609c, 0x1608e, 0x1205e, 0x160de, 0x1605c, 0x1604e, 0x115e0, 0x18af8, 0x1c57e, 0x114f0, 0x18a7c, 0x11478, 0x18a3e, 0x1143c, 0x1141e, 0x1f8b4, 0x116f8, 0x18b7e, 0x1f8b2, 0x1167c, 0x1163e, 0x1f174, 0x1177e, 0x1f172, 0x1e2f4, 0x1e2f2, 0x1c5f4, 0x1c5f2, 0x18bf4, 0x18bf2, 0x135c0, 0x19af0, 0x1cd7c, 0x134e0, 0x19a78, 0x1cd3e, 0x13470, 0x19a3c, 0x13438, 0x19a1e, 0x1341c, 0x1340e, 0x112f0, 0x1897c, 0x136f0, 0x11278, 0x1893e, 0x13678, 0x19b3e, 0x1363c, 0x1121e, 0x1361e, 0x1f89a, 0x1137c, 0x1f9ba, 0x1377c, 0x1133e, 0x1373e, 0x1f13a, 0x1f37a, 0x1e27a, 0x1e6fa, 0x1c4fa, 0x1cdfa, 0x189fa, 0x1bae0, 0x1dd78, 0x1eebe, 0x174c0, 0x1ba70, 0x1dd3c, 0x17460, 0x1ba38, 0x1dd1e, 0x17430, 0x1ba1c, 0x17418, 0x1ba0e, 0x1740c, 0x132e0, 0x19978, 0x1ccbe, 0x176e0, 0x13270, 0x1993c, 0x17670, 0x1bb3c, 0x1991e, 0x17638, 0x1321c, 0x1761c, 0x1320e, 0x1760e, 0x11178, 0x188be, 0x13378, 0x1113c, 0x17778, 0x1333c, 0x1111e, 0x1773c, 0x1331e, 0x1771e, 0x111be, 0x133be, 0x177be, 0x172c0, 0x1b970, 0x1dcbc, 0x17260, 0x1b938, 0x1dc9e, 0x17230, 0x1b91c, 0x17218, 0x1b90e, 0x1720c, 0x17206, 0x13170, 0x198bc, 0x17370, 0x13138, 0x1989e, 0x17338, 0x1b99e, 0x1731c, 0x1310e, 0x1730e, 0x110bc, 0x131bc, 0x1109e, 0x173bc, 0x1319e, 0x1739e, 0x17160, 0x1b8b8, 0x1dc5e, 0x17130, 0x1b89c, 0x17118, 0x1b88e, 0x1710c, 0x17106, 0x130b8, 0x1985e, 0x171b8, 0x1309c, 0x1719c, 0x1308e, 0x1718e, 0x1105e, 0x130de, 0x171de, 0x170b0, 0x1b85c, 0x17098, 0x1b84e, 0x1708c, 0x17086, 0x1305c, 0x170dc, 0x1304e, 0x170ce, 0x17058, 0x1b82e, 0x1704c, 0x17046, 0x1302e, 0x1706e, 0x1702c, 0x17026, 0x10af0, 0x1857c, 0x10a78, 0x1853e, 0x10a3c, 0x10a1e, 0x10b7c, 0x10b3e, 0x1f0ba, 0x1e17a, 0x1c2fa, 0x185fa, 0x11ae0, 0x18d78, 0x1c6be, 0x11a70, 0x18d3c, 0x11a38, 0x18d1e, 0x11a1c, 0x11a0e, 0x10978, 0x184be, 0x11b78, 0x1093c, 0x11b3c, 0x1091e, 0x11b1e, 0x109be, 0x11bbe, 0x13ac0, 0x19d70, 0x1cebc, 0x13a60, 0x19d38, 0x1ce9e, 0x13a30, 0x19d1c, 0x13a18, 0x19d0e, 0x13a0c, 0x13a06, 0x11970, 0x18cbc, 0x13b70, 0x11938, 0x18c9e, 0x13b38, 0x1191c, 0x13b1c, 0x1190e, 0x13b0e, 0x108bc, 0x119bc, 0x1089e, 0x13bbc, 0x1199e, 0x13b9e, 0x1bd60, 0x1deb8, 0x1ef5e, 0x17a40, 0x1bd30, 0x1de9c, 0x17a20, 0x1bd18, 0x1de8e, 0x17a10, 0x1bd0c, 0x17a08, 0x1bd06, 0x17a04, 0x13960, 0x19cb8, 0x1ce5e, 0x17b60, 0x13930, 0x19c9c, 0x17b30, 0x1bd9c, 0x19c8e, 0x17b18, 0x1390c, 0x17b0c, 0x13906, 0x17b06, 0x118b8, 0x18c5e, 0x139b8, 0x1189c, 0x17bb8, 0x1399c, 0x1188e, 0x17b9c, 0x1398e, 0x17b8e, 0x1085e, 0x118de, 0x139de, 0x17bde, 0x17940, 0x1bcb0, 0x1de5c, 0x17920, 0x1bc98, 0x1de4e, 0x17910, 0x1bc8c, 0x17908, 0x1bc86, 0x17904, 0x17902, 0x138b0, 0x19c5c, 0x179b0, 0x13898, 0x19c4e, 0x17998, 0x1bcce, 0x1798c, 0x13886, 0x17986, 0x1185c, 0x138dc, 0x1184e, 0x179dc, 0x138ce, 0x179ce, 0x178a0, 0x1bc58, 0x1de2e, 0x17890, 0x1bc4c, 0x17888, 0x1bc46, 0x17884, 0x17882, 0x13858, 0x19c2e, 0x178d8, 0x1384c, 0x178cc, 0x13846, 0x178c6, 0x1182e, 0x1386e, 0x178ee, 0x17850, 0x1bc2c, 0x17848, 0x1bc26, 0x17844, 0x17842, 0x1382c, 0x1786c, 0x13826, 0x17866, 0x17828, 0x1bc16, 0x17824, 0x17822, 0x13816, 0x17836, 0x10578, 0x182be, 0x1053c, 0x1051e, 0x105be, 0x10d70, 0x186bc, 0x10d38, 0x1869e, 0x10d1c, 0x10d0e, 0x104bc, 0x10dbc, 0x1049e, 0x10d9e, 0x11d60, 0x18eb8, 0x1c75e, 0x11d30, 0x18e9c, 0x11d18, 0x18e8e, 0x11d0c, 0x11d06, 0x10cb8, 0x1865e, 0x11db8, 0x10c9c, 0x11d9c, 0x10c8e, 0x11d8e, 0x1045e, 0x10cde, 0x11dde, 0x13d40, 0x19eb0, 0x1cf5c, 0x13d20, 0x19e98, 0x1cf4e, 0x13d10, 0x19e8c, 0x13d08, 0x19e86, 0x13d04, 0x13d02, 0x11cb0, 0x18e5c, 0x13db0, 0x11c98, 0x18e4e, 0x13d98, 0x19ece, 0x13d8c, 0x11c86, 0x13d86, 0x10c5c, 0x11cdc, 0x10c4e, 0x13ddc, 0x11cce, 0x13dce, 0x1bea0, 0x1df58, 0x1efae, 0x1be90, 0x1df4c, 0x1be88, 0x1df46, 0x1be84, 0x1be82, 0x13ca0, 0x19e58, 0x1cf2e, 0x17da0, 0x13c90, 0x19e4c, 0x17d90, 0x1becc, 0x19e46, 0x17d88, 0x13c84, 0x17d84, 0x13c82, 0x17d82, 0x11c58, 0x18e2e, 0x13cd8, 0x11c4c, 0x17dd8, 0x13ccc, 0x11c46, 0x17dcc, 0x13cc6, 0x17dc6, 0x10c2e, 0x11c6e, 0x13cee, 0x17dee, 0x1be50, 0x1df2c, 0x1be48, 0x1df26, 0x1be44, 0x1be42, 0x13c50, 0x19e2c, 0x17cd0, 0x13c48, 0x19e26, 0x17cc8, 0x1be66, 0x17cc4, 0x13c42, 0x17cc2, 0x11c2c, 0x13c6c, 0x11c26, 0x17cec, 0x13c66, 0x17ce6, 0x1be28, 0x1df16, 0x1be24, 0x1be22, 0x13c28, 0x19e16, 0x17c68, 0x13c24, 0x17c64, 0x13c22, 0x17c62, 0x11c16, 0x13c36, 0x17c76, 0x1be14, 0x1be12, 0x13c14, 0x17c34, 0x13c12, 0x17c32, 0x102bc, 0x1029e, 0x106b8, 0x1835e, 0x1069c, 0x1068e, 0x1025e, 0x106de, 0x10eb0, 0x1875c, 0x10e98, 0x1874e, 0x10e8c, 0x10e86, 0x1065c, 0x10edc, 0x1064e, 0x10ece, 0x11ea0, 0x18f58, 0x1c7ae, 0x11e90, 0x18f4c, 0x11e88, 0x18f46, 0x11e84, 0x11e82, 0x10e58, 0x1872e, 0x11ed8, 0x18f6e, 0x11ecc, 0x10e46, 0x11ec6, 0x1062e, 0x10e6e, 0x11eee, 0x19f50, 0x1cfac, 0x19f48, 0x1cfa6, 0x19f44, 0x19f42, 0x11e50, 0x18f2c, 0x13ed0, 0x19f6c, 0x18f26, 0x13ec8, 0x11e44, 0x13ec4, 0x11e42, 0x13ec2, 0x10e2c, 0x11e6c, 0x10e26, 0x13eec, 0x11e66, 0x13ee6, 0x1dfa8, 0x1efd6, 0x1dfa4, 0x1dfa2, 0x19f28, 0x1cf96, 0x1bf68, 0x19f24, 0x1bf64, 0x19f22, 0x1bf62, 0x11e28, 0x18f16, 0x13e68, 0x11e24, 0x17ee8, 0x13e64, 0x11e22, 0x17ee4, 0x13e62, 0x17ee2, 0x10e16, 0x11e36, 0x13e76, 0x17ef6, 0x1df94, 0x1df92, 0x19f14, 0x1bf34, 0x19f12, 0x1bf32, 0x11e14, 0x13e34, 0x11e12, 0x17e74, 0x13e32, 0x17e72, 0x1df8a, 0x19f0a, 0x1bf1a, 0x11e0a, 0x13e1a, 0x17e3a, 0x1035c, 0x1034e, 0x10758, 0x183ae, 0x1074c, 0x10746, 0x1032e, 0x1076e, 0x10f50, 0x187ac, 0x10f48, 0x187a6, 0x10f44, 0x10f42, 0x1072c, 0x10f6c, 0x10726, 0x10f66, 0x18fa8, 0x1c7d6, 0x18fa4, 0x18fa2, 0x10f28, 0x18796, 0x11f68, 0x18fb6, 0x11f64, 0x10f22, 0x11f62, 0x10716, 0x10f36, 0x11f76, 0x1cfd4, 0x1cfd2, 0x18f94, 0x19fb4, 0x18f92, 0x19fb2, 0x10f14, 0x11f34, 0x10f12, 0x13f74, 0x11f32, 0x13f72, 0x1cfca, 0x18f8a, 0x19f9a, 0x10f0a, 0x11f1a, 0x13f3a, 0x103ac, 0x103a6, 0x107a8, 0x183d6, 0x107a4, 0x107a2, 0x10396, 0x107b6, 0x187d4, 0x187d2, 0x10794, 0x10fb4, 0x10792, 0x10fb2, 0x1c7ea, }, } func getCodeword(tableId int, word int) int { return codewords[tableId][word] } barcode-1.0.1/pdf417/dimensions.go000066400000000000000000000016301343272050500166150ustar00rootroot00000000000000package pdf417 import "math" const ( minCols = 2 maxCols = 30 maxRows = 30 minRows = 2 moduleHeight = 2 preferred_ratio = 3.0 ) func calculateNumberOfRows(m, k, c int) int { r := ((m + 1 + k) / c) + 1 if c*r >= (m + 1 + k + c) { r-- } return r } func calcDimensions(dataWords, eccWords int) (cols, rows int) { ratio := 0.0 cols = 0 rows = 0 for c := minCols; c <= maxCols; c++ { r := calculateNumberOfRows(dataWords, eccWords, c) if r < minRows { break } if r > maxRows { continue } newRatio := float64(17*cols+69) / float64(rows*moduleHeight) if rows != 0 && math.Abs(newRatio-preferred_ratio) > math.Abs(ratio-preferred_ratio) { continue } ratio = newRatio cols = c rows = r } if rows == 0 { r := calculateNumberOfRows(dataWords, eccWords, minCols) if r < minRows { rows = minRows cols = minCols } } return } barcode-1.0.1/pdf417/encoder.go000066400000000000000000000065451343272050500160760ustar00rootroot00000000000000// Package pdf417 can create PDF-417 barcodes package pdf417 import ( "fmt" "github.com/boombuler/barcode" "github.com/boombuler/barcode/utils" ) const ( padding_codeword = 900 ) // Encodes the given data as PDF417 barcode. // securityLevel should be between 0 and 8. The higher the number, the more // additional error-correction codes are added. func Encode(data string, securityLevel byte) (barcode.Barcode, error) { if securityLevel >= 9 { return nil, fmt.Errorf("Invalid security level %d", securityLevel) } sl := securitylevel(securityLevel) dataWords, err := highlevelEncode(data) if err != nil { return nil, err } columns, rows := calcDimensions(len(dataWords), sl.ErrorCorrectionWordCount()) if columns < minCols || columns > maxCols || rows < minRows || rows > maxRows { return nil, fmt.Errorf("Unable to fit data in barcode") } barcode := new(pdfBarcode) barcode.data = data codeWords, err := encodeData(dataWords, columns, sl) if err != nil { return nil, err } grid := [][]int{} for i := 0; i < len(codeWords); i += columns { grid = append(grid, codeWords[i:min(i+columns, len(codeWords))]) } codes := [][]int{} for rowNum, row := range grid { table := rowNum % 3 rowCodes := make([]int, 0, columns+4) rowCodes = append(rowCodes, start_word) rowCodes = append(rowCodes, getCodeword(table, getLeftCodeWord(rowNum, rows, columns, securityLevel))) for _, word := range row { rowCodes = append(rowCodes, getCodeword(table, word)) } rowCodes = append(rowCodes, getCodeword(table, getRightCodeWord(rowNum, rows, columns, securityLevel))) rowCodes = append(rowCodes, stop_word) codes = append(codes, rowCodes) } barcode.code = renderBarcode(codes) barcode.width = (columns+4)*17 + 1 return barcode, nil } func encodeData(dataWords []int, columns int, sl securitylevel) ([]int, error) { dataCount := len(dataWords) ecCount := sl.ErrorCorrectionWordCount() padWords := getPadding(dataCount, ecCount, columns) dataWords = append(dataWords, padWords...) length := len(dataWords) + 1 dataWords = append([]int{length}, dataWords...) ecWords := sl.Compute(dataWords) return append(dataWords, ecWords...), nil } func getLeftCodeWord(rowNum int, rows int, columns int, securityLevel byte) int { tableId := rowNum % 3 var x int switch tableId { case 0: x = (rows - 3) / 3 case 1: x = int(securityLevel) * 3 x += (rows - 1) % 3 case 2: x = columns - 1 } return 30*(rowNum/3) + x } func getRightCodeWord(rowNum int, rows int, columns int, securityLevel byte) int { tableId := rowNum % 3 var x int switch tableId { case 0: x = columns - 1 case 1: x = (rows - 1) / 3 case 2: x = int(securityLevel) * 3 x += (rows - 1) % 3 } return 30*(rowNum/3) + x } func min(a, b int) int { if a <= b { return a } return b } func getPadding(dataCount int, ecCount int, columns int) []int { totalCount := dataCount + ecCount + 1 mod := totalCount % columns padding := []int{} if mod > 0 { padCount := columns - mod padding = make([]int, padCount) for i := 0; i < padCount; i++ { padding[i] = padding_codeword } } return padding } func renderBarcode(codes [][]int) *utils.BitList { bl := new(utils.BitList) for _, row := range codes { lastIdx := len(row) - 1 for i, col := range row { if i == lastIdx { bl.AddBits(col, 18) } else { bl.AddBits(col, 17) } } } return bl } barcode-1.0.1/pdf417/errorcorrection.go000066400000000000000000000140371343272050500176730ustar00rootroot00000000000000package pdf417 type securitylevel byte func (level securitylevel) ErrorCorrectionWordCount() int { return 1 << (uint(level) + 1) } var correctionFactors = [][]int{ // Level 0 []int{27, 917}, // Level 1 []int{522, 568, 723, 809}, // Level 2 []int{237, 308, 436, 284, 646, 653, 428, 379}, // Level 3 []int{ 274, 562, 232, 755, 599, 524, 801, 132, 295, 116, 442, 428, 295, 42, 176, 65, }, // Level 4 []int{ 361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, 284, 193, 517, 273, 494, 263, 147, 593, 800, 571, 320, 803, 133, 231, 390, 685, 330, 63, 410, }, // Level 5 []int{ 539, 422, 6, 93, 862, 771, 453, 106, 610, 287, 107, 505, 733, 877, 381, 612, 723, 476, 462, 172, 430, 609, 858, 822, 543, 376, 511, 400, 672, 762, 283, 184, 440, 35, 519, 31, 460, 594, 225, 535, 517, 352, 605, 158, 651, 201, 488, 502, 648, 733, 717, 83, 404, 97, 280, 771, 840, 629, 4, 381, 843, 623, 264, 543, }, // Level 6 []int{ 521, 310, 864, 547, 858, 580, 296, 379, 53, 779, 897, 444, 400, 925, 749, 415, 822, 93, 217, 208, 928, 244, 583, 620, 246, 148, 447, 631, 292, 908, 490, 704, 516, 258, 457, 907, 594, 723, 674, 292, 272, 96, 684, 432, 686, 606, 860, 569, 193, 219, 129, 186, 236, 287, 192, 775, 278, 173, 40, 379, 712, 463, 646, 776, 171, 491, 297, 763, 156, 732, 95, 270, 447, 90, 507, 48, 228, 821, 808, 898, 784, 663, 627, 378, 382, 262, 380, 602, 754, 336, 89, 614, 87, 432, 670, 616, 157, 374, 242, 726, 600, 269, 375, 898, 845, 454, 354, 130, 814, 587, 804, 34, 211, 330, 539, 297, 827, 865, 37, 517, 834, 315, 550, 86, 801, 4, 108, 539, }, // Level 7 []int{ 524, 894, 75, 766, 882, 857, 74, 204, 82, 586, 708, 250, 905, 786, 138, 720, 858, 194, 311, 913, 275, 190, 375, 850, 438, 733, 194, 280, 201, 280, 828, 757, 710, 814, 919, 89, 68, 569, 11, 204, 796, 605, 540, 913, 801, 700, 799, 137, 439, 418, 592, 668, 353, 859, 370, 694, 325, 240, 216, 257, 284, 549, 209, 884, 315, 70, 329, 793, 490, 274, 877, 162, 749, 812, 684, 461, 334, 376, 849, 521, 307, 291, 803, 712, 19, 358, 399, 908, 103, 511, 51, 8, 517, 225, 289, 470, 637, 731, 66, 255, 917, 269, 463, 830, 730, 433, 848, 585, 136, 538, 906, 90, 2, 290, 743, 199, 655, 903, 329, 49, 802, 580, 355, 588, 188, 462, 10, 134, 628, 320, 479, 130, 739, 71, 263, 318, 374, 601, 192, 605, 142, 673, 687, 234, 722, 384, 177, 752, 607, 640, 455, 193, 689, 707, 805, 641, 48, 60, 732, 621, 895, 544, 261, 852, 655, 309, 697, 755, 756, 60, 231, 773, 434, 421, 726, 528, 503, 118, 49, 795, 32, 144, 500, 238, 836, 394, 280, 566, 319, 9, 647, 550, 73, 914, 342, 126, 32, 681, 331, 792, 620, 60, 609, 441, 180, 791, 893, 754, 605, 383, 228, 749, 760, 213, 54, 297, 134, 54, 834, 299, 922, 191, 910, 532, 609, 829, 189, 20, 167, 29, 872, 449, 83, 402, 41, 656, 505, 579, 481, 173, 404, 251, 688, 95, 497, 555, 642, 543, 307, 159, 924, 558, 648, 55, 497, 10, }, // Level 8 []int{ 352, 77, 373, 504, 35, 599, 428, 207, 409, 574, 118, 498, 285, 380, 350, 492, 197, 265, 920, 155, 914, 299, 229, 643, 294, 871, 306, 88, 87, 193, 352, 781, 846, 75, 327, 520, 435, 543, 203, 666, 249, 346, 781, 621, 640, 268, 794, 534, 539, 781, 408, 390, 644, 102, 476, 499, 290, 632, 545, 37, 858, 916, 552, 41, 542, 289, 122, 272, 383, 800, 485, 98, 752, 472, 761, 107, 784, 860, 658, 741, 290, 204, 681, 407, 855, 85, 99, 62, 482, 180, 20, 297, 451, 593, 913, 142, 808, 684, 287, 536, 561, 76, 653, 899, 729, 567, 744, 390, 513, 192, 516, 258, 240, 518, 794, 395, 768, 848, 51, 610, 384, 168, 190, 826, 328, 596, 786, 303, 570, 381, 415, 641, 156, 237, 151, 429, 531, 207, 676, 710, 89, 168, 304, 402, 40, 708, 575, 162, 864, 229, 65, 861, 841, 512, 164, 477, 221, 92, 358, 785, 288, 357, 850, 836, 827, 736, 707, 94, 8, 494, 114, 521, 2, 499, 851, 543, 152, 729, 771, 95, 248, 361, 578, 323, 856, 797, 289, 51, 684, 466, 533, 820, 669, 45, 902, 452, 167, 342, 244, 173, 35, 463, 651, 51, 699, 591, 452, 578, 37, 124, 298, 332, 552, 43, 427, 119, 662, 777, 475, 850, 764, 364, 578, 911, 283, 711, 472, 420, 245, 288, 594, 394, 511, 327, 589, 777, 699, 688, 43, 408, 842, 383, 721, 521, 560, 644, 714, 559, 62, 145, 873, 663, 713, 159, 672, 729, 624, 59, 193, 417, 158, 209, 563, 564, 343, 693, 109, 608, 563, 365, 181, 772, 677, 310, 248, 353, 708, 410, 579, 870, 617, 841, 632, 860, 289, 536, 35, 777, 618, 586, 424, 833, 77, 597, 346, 269, 757, 632, 695, 751, 331, 247, 184, 45, 787, 680, 18, 66, 407, 369, 54, 492, 228, 613, 830, 922, 437, 519, 644, 905, 789, 420, 305, 441, 207, 300, 892, 827, 141, 537, 381, 662, 513, 56, 252, 341, 242, 797, 838, 837, 720, 224, 307, 631, 61, 87, 560, 310, 756, 665, 397, 808, 851, 309, 473, 795, 378, 31, 647, 915, 459, 806, 590, 731, 425, 216, 548, 249, 321, 881, 699, 535, 673, 782, 210, 815, 905, 303, 843, 922, 281, 73, 469, 791, 660, 162, 498, 308, 155, 422, 907, 817, 187, 62, 16, 425, 535, 336, 286, 437, 375, 273, 610, 296, 183, 923, 116, 667, 751, 353, 62, 366, 691, 379, 687, 842, 37, 357, 720, 742, 330, 5, 39, 923, 311, 424, 242, 749, 321, 54, 669, 316, 342, 299, 534, 105, 667, 488, 640, 672, 576, 540, 316, 486, 721, 610, 46, 656, 447, 171, 616, 464, 190, 531, 297, 321, 762, 752, 533, 175, 134, 14, 381, 433, 717, 45, 111, 20, 596, 284, 736, 138, 646, 411, 877, 669, 141, 919, 45, 780, 407, 164, 332, 899, 165, 726, 600, 325, 498, 655, 357, 752, 768, 223, 849, 647, 63, 310, 863, 251, 366, 304, 282, 738, 675, 410, 389, 244, 31, 121, 303, 263, }, } func (level securitylevel) Compute(data []int) []int { // Correction factors for the given level factors := correctionFactors[int(level)] // Number of correction code words count := level.ErrorCorrectionWordCount() // Correction code words array, prepopulated with zeros ecWords := make([]int, count) for _, value := range data { temp := (value + ecWords[0]) % 929 for i := count - 1; i >= 0; i-- { add := 0 if i > 0 { add = ecWords[count-i] } ecWords[count-1-i] = (add + 929 - (temp*factors[i])%929) % 929 } } for key, word := range ecWords { if word > 0 { ecWords[key] = 929 - word } } return ecWords } barcode-1.0.1/pdf417/errorcorrection_test.go000066400000000000000000000150021343272050500207230ustar00rootroot00000000000000package pdf417 import ( "testing" ) var inputData = []int{16, 902, 1, 278, 827, 900, 295, 902, 2, 326, 823, 544, 900, 149, 900, 900} func TestReedSolomonComputeLevel0(t *testing.T) { var level securitylevel = 0 expected := []int{156, 765} compareIntSlice(t, expected, level.Compute(inputData), "SecLvl 0") } func TestReedSolomonComputeLevel1(t *testing.T) { var level securitylevel = 1 expected := []int{168, 875, 63, 355} compareIntSlice(t, expected, level.Compute(inputData), "SecLvl 1") } func TestReedSolomonComputeLevel2(t *testing.T) { var level securitylevel = 2 expected := []int{628, 715, 393, 299, 863, 601, 169, 708} compareIntSlice(t, expected, level.Compute(inputData), "SecLvl 2") } func TestReedSolomonComputeLevel3(t *testing.T) { var level securitylevel = 3 expected := []int{232, 176, 793, 616, 476, 406, 855, 445, 84, 518, 522, 721, 607, 2, 42, 578} compareIntSlice(t, expected, level.Compute(inputData), "SecLvl 3") } func TestReedSolomonComputeLevel4(t *testing.T) { var level securitylevel = 4 expected := []int{281, 156, 276, 668, 44, 252, 877, 30, 549, 856, 773, 639, 420, 330, 693, 329, 283, 723, 480, 482, 102, 925, 535, 892, 374, 472, 837, 331, 343, 608, 390, 364} compareIntSlice(t, expected, level.Compute(inputData), "SecLvl 4") } func TestReedSolomonComputeLevel5(t *testing.T) { var level securitylevel = 5 expected := []int{31, 850, 18, 870, 53, 477, 837, 130, 533, 186, 266, 450, 39, 492, 542, 653, 499, 887, 618, 103, 364, 313, 906, 396, 270, 735, 593, 81, 557, 712, 810, 48, 167, 533, 205, 577, 503, 126, 449, 189, 859, 471, 493, 849, 554, 76, 878, 893, 168, 497, 251, 704, 311, 650, 283, 268, 462, 223, 659, 763, 176, 34, 544, 304} compareIntSlice(t, expected, level.Compute(inputData), "SecLvl 5") } func TestReedSolomonComputeLevel6(t *testing.T) { var level securitylevel = 6 expected := []int{345, 775, 909, 489, 650, 568, 869, 577, 574, 349, 885, 317, 492, 222, 783, 451, 647, 385, 168, 366, 118, 655, 643, 551, 179, 880, 880, 752, 132, 206, 765, 862, 727, 240, 32, 266, 911, 287, 813, 437, 868, 201, 681, 867, 567, 398, 508, 564, 504, 676, 785, 554, 831, 566, 424, 93, 515, 275, 61, 544, 272, 621, 374, 922, 779, 663, 789, 295, 631, 536, 755, 465, 485, 416, 76, 412, 76, 431, 28, 614, 767, 419, 600, 779, 94, 584, 647, 846, 121, 97, 790, 205, 424, 793, 263, 271, 694, 522, 437, 817, 382, 164, 113, 849, 178, 602, 554, 261, 415, 737, 401, 675, 203, 271, 649, 120, 765, 209, 522, 687, 420, 32, 60, 266, 270, 228, 304, 270} compareIntSlice(t, expected, level.Compute(inputData), "SecLvl 6") } func TestReedSolomonComputeLevel7(t *testing.T) { var level securitylevel = 7 expected := []int{142, 203, 799, 4, 105, 137, 793, 914, 225, 636, 60, 171, 490, 180, 414, 141, 399, 599, 829, 288, 108, 268, 444, 481, 795, 146, 655, 778, 189, 32, 597, 206, 208, 711, 845, 608, 642, 636, 540, 795, 845, 466, 492, 659, 138, 800, 912, 171, 92, 438, 225, 301, 777, 449, 230, 448, 326, 182, 892, 681, 543, 582, 732, 758, 162, 587, 685, 378, 646, 356, 354, 25, 839, 839, 556, 253, 501, 771, 745, 616, 473, 293, 669, 822, 613, 684, 229, 265, 110, 438, 144, 727, 317, 605, 414, 497, 82, 278, 267, 323, 43, 894, 624, 282, 790, 579, 430, 255, 802, 553, 922, 604, 68, 692, 809, 909, 663, 589, 735, 670, 298, 158, 201, 68, 124, 64, 67, 338, 694, 373, 225, 579, 309, 699, 920, 432, 717, 72, 126, 819, 142, 755, 473, 630, 331, 758, 730, 65, 359, 451, 236, 16, 56, 31, 87, 587, 125, 385, 384, 197, 352, 383, 173, 271, 38, 558, 810, 260, 521, 680, 7, 319, 650, 334, 695, 708, 0, 562, 365, 204, 114, 185, 560, 746, 767, 449, 797, 688, 63, 135, 818, 805, 3, 536, 908, 532, 400, 698, 49, 212, 630, 93, 157, 275, 3, 20, 611, 179, 302, 282, 876, 665, 241, 206, 474, 80, 217, 460, 462, 751, 719, 571, 536, 794, 522, 385, 598, 756, 162, 212, 758, 662, 361, 223, 587, 857, 503, 382, 615, 86, 283, 541, 847, 518, 406, 736, 486, 408, 226, 342, 784, 772, 211, 888, 234, 335} compareIntSlice(t, expected, level.Compute(inputData), "SecLvl 7") } func TestReedSolomonComputeLevel8(t *testing.T) { var level securitylevel = 8 expected := []int{538, 446, 840, 510, 163, 708, 177, 666, 423, 600, 707, 913, 770, 571, 156, 683, 676, 697, 898, 776, 128, 851, 163, 854, 135, 661, 880, 279, 92, 324, 397, 207, 379, 223, 574, 9, 70, 858, 878, 579, 61, 551, 261, 388, 315, 856, 266, 865, 923, 38, 313, 62, 381, 198, 265, 256, 385, 878, 347, 532, 821, 53, 855, 225, 697, 826, 263, 334, 207, 565, 460, 496, 705, 599, 383, 289, 178, 168, 401, 268, 555, 190, 922, 284, 180, 810, 891, 832, 636, 813, 894, 495, 701, 484, 204, 793, 129, 164, 444, 228, 636, 98, 809, 57, 736, 697, 727, 534, 889, 480, 898, 773, 234, 851, 880, 843, 714, 443, 412, 489, 578, 468, 367, 663, 11, 686, 319, 352, 345, 670, 106, 106, 219, 466, 439, 350, 538, 66, 852, 175, 465, 731, 332, 110, 926, 491, 18, 422, 736, 797, 624, 376, 728, 526, 735, 200, 502, 923, 789, 529, 923, 706, 384, 869, 172, 548, 520, 463, 813, 384, 793, 231, 190, 653, 864, 351, 400, 525, 487, 828, 654, 307, 141, 638, 770, 775, 282, 54, 758, 197, 492, 320, 86, 790, 275, 237, 923, 25, 591, 605, 61, 824, 79, 631, 532, 337, 867, 423, 340, 597, 682, 923, 287, 408, 503, 361, 881, 196, 468, 759, 746, 389, 124, 784, 198, 865, 538, 451, 178, 772, 653, 121, 497, 598, 711, 716, 241, 159, 429, 88, 799, 761, 639, 105, 54, 807, 351, 435, 793, 873, 360, 8, 881, 479, 693, 576, 849, 875, 771, 621, 134, 863, 8, 171, 799, 924, 103, 63, 491, 538, 597, 855, 697, 499, 7, 886, 286, 85, 107, 220, 319, 124, 197, 150, 729, 899, 585, 540, 676, 414, 256, 856, 596, 259, 882, 436, 26, 273, 753, 127, 679, 390, 654, 42, 276, 420, 247, 629, 116, 803, 131, 25, 403, 645, 462, 897, 151, 622, 108, 167, 227, 831, 887, 662, 739, 263, 829, 56, 624, 317, 908, 378, 39, 393, 861, 338, 202, 179, 907, 109, 360, 736, 554, 342, 594, 125, 433, 394, 195, 698, 844, 912, 530, 842, 337, 294, 528, 231, 735, 93, 8, 579, 42, 148, 609, 233, 782, 887, 888, 915, 620, 78, 137, 161, 282, 217, 775, 564, 33, 195, 36, 584, 679, 775, 476, 309, 230, 303, 708, 143, 679, 502, 814, 193, 508, 532, 542, 580, 603, 641, 338, 361, 542, 537, 810, 394, 764, 136, 167, 611, 881, 775, 267, 433, 142, 202, 828, 363, 101, 728, 660, 583, 483, 786, 717, 190, 809, 422, 567, 741, 695, 310, 120, 177, 47, 494, 345, 508, 16, 639, 402, 625, 286, 298, 358, 54, 705, 916, 291, 424, 375, 883, 655, 675, 498, 498, 884, 862, 365, 310, 805, 763, 855, 354, 777, 543, 53, 773, 120, 408, 234, 728, 438, 914, 3, 670, 546, 465, 449, 923, 51, 546, 709, 648, 96, 320, 682, 326, 848, 234, 855, 791, 20, 97, 901, 351, 317, 764, 767, 312, 206, 139, 610, 578, 646, 264, 389, 238, 675, 595, 430, 88} compareIntSlice(t, expected, level.Compute(inputData), "SecLvl 8") } barcode-1.0.1/pdf417/highlevel.go000066400000000000000000000164571343272050500164310ustar00rootroot00000000000000package pdf417 import ( "errors" "math/big" "github.com/boombuler/barcode/utils" ) type encodingMode byte type subMode byte const ( encText encodingMode = iota encNumeric encBinary subUpper subMode = iota subLower subMixed subPunct latch_to_text = 900 latch_to_byte_padded = 901 latch_to_numeric = 902 latch_to_byte = 924 shift_to_byte = 913 min_numeric_count = 13 ) var ( mixedMap map[rune]int punctMap map[rune]int ) func init() { mixedMap = make(map[rune]int) mixedRaw := []rune{ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 38, 13, 9, 44, 58, 35, 45, 46, 36, 47, 43, 37, 42, 61, 94, 0, 32, 0, 0, 0, } for idx, ch := range mixedRaw { if ch > 0 { mixedMap[ch] = idx } } punctMap = make(map[rune]int) punctRaw := []rune{ 59, 60, 62, 64, 91, 92, 93, 95, 96, 126, 33, 13, 9, 44, 58, 10, 45, 46, 36, 47, 34, 124, 42, 40, 41, 63, 123, 125, 39, 0, } for idx, ch := range punctRaw { if ch > 0 { punctMap[ch] = idx } } } func determineConsecutiveDigitCount(data []rune) int { cnt := 0 for _, r := range data { if utils.RuneToInt(r) == -1 { break } cnt++ } return cnt } func encodeNumeric(digits []rune) ([]int, error) { digitCount := len(digits) chunkCount := digitCount / 44 if digitCount%44 != 0 { chunkCount++ } codeWords := []int{} for i := 0; i < chunkCount; i++ { start := i * 44 end := start + 44 if end > digitCount { end = digitCount } chunk := digits[start:end] chunkNum := big.NewInt(0) _, ok := chunkNum.SetString("1"+string(chunk), 10) if !ok { return nil, errors.New("Failed converting: " + string(chunk)) } cws := []int{} for chunkNum.Cmp(big.NewInt(0)) > 0 { newChunk, cw := chunkNum.DivMod(chunkNum, big.NewInt(900), big.NewInt(0)) chunkNum = newChunk cws = append([]int{int(cw.Int64())}, cws...) } codeWords = append(codeWords, cws...) } return codeWords, nil } func determineConsecutiveTextCount(msg []rune) int { result := 0 isText := func(ch rune) bool { return ch == '\t' || ch == '\n' || ch == '\r' || (ch >= 32 && ch <= 126) } for i, ch := range msg { numericCount := determineConsecutiveDigitCount(msg[i:]) if numericCount >= min_numeric_count || (numericCount == 0 && !isText(ch)) { break } result++ } return result } func encodeText(text []rune, submode subMode) (subMode, []int) { isAlphaUpper := func(ch rune) bool { return ch == ' ' || (ch >= 'A' && ch <= 'Z') } isAlphaLower := func(ch rune) bool { return ch == ' ' || (ch >= 'a' && ch <= 'z') } isMixed := func(ch rune) bool { _, ok := mixedMap[ch] return ok } isPunctuation := func(ch rune) bool { _, ok := punctMap[ch] return ok } idx := 0 var tmp []int for idx < len(text) { ch := text[idx] switch submode { case subUpper: if isAlphaUpper(ch) { if ch == ' ' { tmp = append(tmp, 26) //space } else { tmp = append(tmp, int(ch-'A')) } } else { if isAlphaLower(ch) { submode = subLower tmp = append(tmp, 27) // lower latch continue } else if isMixed(ch) { submode = subMixed tmp = append(tmp, 28) // mixed latch continue } else { tmp = append(tmp, 29) // punctuation switch tmp = append(tmp, punctMap[ch]) break } } break case subLower: if isAlphaLower(ch) { if ch == ' ' { tmp = append(tmp, 26) //space } else { tmp = append(tmp, int(ch-'a')) } } else { if isAlphaUpper(ch) { tmp = append(tmp, 27) //upper switch tmp = append(tmp, int(ch-'A')) break } else if isMixed(ch) { submode = subMixed tmp = append(tmp, 28) //mixed latch continue } else { tmp = append(tmp, 29) //punctuation switch tmp = append(tmp, punctMap[ch]) break } } break case subMixed: if isMixed(ch) { tmp = append(tmp, mixedMap[ch]) } else { if isAlphaUpper(ch) { submode = subUpper tmp = append(tmp, 28) //upper latch continue } else if isAlphaLower(ch) { submode = subLower tmp = append(tmp, 27) //lower latch continue } else { if idx+1 < len(text) { next := text[idx+1] if isPunctuation(next) { submode = subPunct tmp = append(tmp, 25) //punctuation latch continue } } tmp = append(tmp, 29) //punctuation switch tmp = append(tmp, punctMap[ch]) } } break default: //subPunct if isPunctuation(ch) { tmp = append(tmp, punctMap[ch]) } else { submode = subUpper tmp = append(tmp, 29) //upper latch continue } } idx++ } h := 0 result := []int{} for i, val := range tmp { if i%2 != 0 { h = (h * 30) + val result = append(result, h) } else { h = val } } if len(tmp)%2 != 0 { result = append(result, (h*30)+29) } return submode, result } func determineConsecutiveBinaryCount(msg []byte) int { result := 0 for i, _ := range msg { numericCount := determineConsecutiveDigitCount([]rune(string(msg[i:]))) if numericCount >= min_numeric_count { break } textCount := determineConsecutiveTextCount([]rune(string(msg[i:]))) if textCount > 5 { break } result++ } return result } func encodeBinary(data []byte, startmode encodingMode) []int { result := []int{} count := len(data) if count == 1 && startmode == encText { result = append(result, shift_to_byte) } else if (count % 6) == 0 { result = append(result, latch_to_byte) } else { result = append(result, latch_to_byte_padded) } idx := 0 // Encode sixpacks if count >= 6 { words := make([]int, 5) for (count - idx) >= 6 { var t int64 = 0 for i := 0; i < 6; i++ { t = t << 8 t += int64(data[idx+i]) } for i := 0; i < 5; i++ { words[4-i] = int(t % 900) t = t / 900 } result = append(result, words...) idx += 6 } } //Encode rest (remaining n<5 bytes if any) for i := idx; i < count; i++ { result = append(result, int(data[i]&0xff)) } return result } func highlevelEncode(dataStr string) ([]int, error) { encodingMode := encText textSubMode := subUpper result := []int{} data := []byte(dataStr) for len(data) > 0 { numericCount := determineConsecutiveDigitCount([]rune(string(data))) if numericCount >= min_numeric_count || numericCount == len(data) { result = append(result, latch_to_numeric) encodingMode = encNumeric textSubMode = subUpper numData, err := encodeNumeric([]rune(string(data[:numericCount]))) if err != nil { return nil, err } result = append(result, numData...) data = data[numericCount:] } else { textCount := determineConsecutiveTextCount([]rune(string(data))) if textCount >= 5 || textCount == len(data) { if encodingMode != encText { result = append(result, latch_to_text) encodingMode = encText textSubMode = subUpper } var txtData []int textSubMode, txtData = encodeText([]rune(string(data[:textCount])), textSubMode) result = append(result, txtData...) data = data[textCount:] } else { binaryCount := determineConsecutiveBinaryCount(data) if binaryCount == 0 { binaryCount = 1 } bytes := data[:binaryCount] if len(bytes) != 1 || encodingMode != encText { encodingMode = encBinary textSubMode = subUpper } byteData := encodeBinary(bytes, encodingMode) result = append(result, byteData...) data = data[binaryCount:] } } } return result, nil } barcode-1.0.1/pdf417/highlevel_test.go000066400000000000000000000022051343272050500174520ustar00rootroot00000000000000package pdf417 import "testing" func compareIntSlice(t *testing.T, expected, actual []int, testStr string) { if len(actual) != len(expected) { t.Errorf("Invalid slice size. Expected %d got %d while encoding %q", len(expected), len(actual), testStr) return } for i, a := range actual { if e := expected[i]; e != a { t.Errorf("Unexpected value at position %d. Expected %d got %d while encoding %q", i, e, a, testStr) } } } func TestHighlevelEncode(t *testing.T) { runTest := func(msg string, expected ...int) { if codes, err := highlevelEncode(msg); err != nil { t.Error(err) } else { compareIntSlice(t, expected, codes, msg) } } runTest("01234", 902, 112, 434) runTest("Super !", 567, 615, 137, 809, 329) runTest("Super ", 567, 615, 137, 809) runTest("ABC123", 1, 88, 32, 119) runTest("123ABC", 841, 63, 840, 32) } func TestBinaryEncoder(t *testing.T) { runTest := func(msg string, expected ...int) { codes := encodeBinary([]byte(msg), encText) compareIntSlice(t, expected, codes, msg) } runTest("alcool", 924, 163, 238, 432, 766, 244) runTest("alcoolique", 901, 163, 238, 432, 766, 244, 105, 113, 117, 101) } barcode-1.0.1/pdf417/pdfcode.go000066400000000000000000000013151343272050500160510ustar00rootroot00000000000000package pdf417 import ( "image" "image/color" "github.com/boombuler/barcode" "github.com/boombuler/barcode/utils" ) type pdfBarcode struct { data string width int code *utils.BitList } func (c *pdfBarcode) Metadata() barcode.Metadata { return barcode.Metadata{barcode.TypePDF, 2} } func (c *pdfBarcode) Content() string { return c.data } func (c *pdfBarcode) ColorModel() color.Model { return color.Gray16Model } func (c *pdfBarcode) Bounds() image.Rectangle { height := c.code.Len() / c.width return image.Rect(0, 0, c.width, height*moduleHeight) } func (c *pdfBarcode) At(x, y int) color.Color { if c.code.GetBit((y/moduleHeight)*c.width + x) { return color.Black } return color.White } barcode-1.0.1/qr/000077500000000000000000000000001343272050500135335ustar00rootroot00000000000000barcode-1.0.1/qr/alphanumeric.go000066400000000000000000000026221343272050500165340ustar00rootroot00000000000000package qr import ( "errors" "fmt" "strings" "github.com/boombuler/barcode/utils" ) const charSet string = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:" func stringToAlphaIdx(content string) <-chan int { result := make(chan int) go func() { for _, r := range content { idx := strings.IndexRune(charSet, r) result <- idx if idx < 0 { break } } close(result) }() return result } func encodeAlphaNumeric(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) { contentLenIsOdd := len(content)%2 == 1 contentBitCount := (len(content) / 2) * 11 if contentLenIsOdd { contentBitCount += 6 } vi := findSmallestVersionInfo(ecl, alphaNumericMode, contentBitCount) if vi == nil { return nil, nil, errors.New("To much data to encode") } res := new(utils.BitList) res.AddBits(int(alphaNumericMode), 4) res.AddBits(len(content), vi.charCountBits(alphaNumericMode)) encoder := stringToAlphaIdx(content) for idx := 0; idx < len(content)/2; idx++ { c1 := <-encoder c2 := <-encoder if c1 < 0 || c2 < 0 { return nil, nil, fmt.Errorf("\"%s\" can not be encoded as %s", content, AlphaNumeric) } res.AddBits(c1*45+c2, 11) } if contentLenIsOdd { c := <-encoder if c < 0 { return nil, nil, fmt.Errorf("\"%s\" can not be encoded as %s", content, AlphaNumeric) } res.AddBits(c, 6) } addPaddingAndTerminator(res, vi) return res, vi, nil } barcode-1.0.1/qr/alphanumeric_test.go000066400000000000000000000017221343272050500175730ustar00rootroot00000000000000package qr import ( "bytes" "testing" ) func makeString(length int, content string) string { res := "" for i := 0; i < length; i++ { res += content } return res } func Test_AlphaNumericEncoding(t *testing.T) { encode := AlphaNumeric.getEncoder() x, vi, err := encode("HELLO WORLD", M) if x == nil || vi == nil || vi.Version != 1 || bytes.Compare(x.GetBytes(), []byte{32, 91, 11, 120, 209, 114, 220, 77, 67, 64, 236, 17, 236, 17, 236, 17}) != 0 { t.Errorf("\"HELLO WORLD\" failed to encode: %s", err) } x, vi, err = encode(makeString(4296, "A"), L) if x == nil || vi == nil || err != nil { t.Fail() } x, vi, err = encode(makeString(4297, "A"), L) if x != nil || vi != nil || err == nil { t.Fail() } x, vi, err = encode("ABc", L) if x != nil || vi != nil || err == nil { t.Fail() } x, vi, err = encode("hello world", M) if x != nil || vi != nil || err == nil { t.Error("\"hello world\" should not be encodable in alphanumeric mode") } } barcode-1.0.1/qr/automatic.go000066400000000000000000000010751343272050500160530ustar00rootroot00000000000000package qr import ( "fmt" "github.com/boombuler/barcode/utils" ) func encodeAuto(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) { bits, vi, _ := Numeric.getEncoder()(content, ecl) if bits != nil && vi != nil { return bits, vi, nil } bits, vi, _ = AlphaNumeric.getEncoder()(content, ecl) if bits != nil && vi != nil { return bits, vi, nil } bits, vi, _ = Unicode.getEncoder()(content, ecl) if bits != nil && vi != nil { return bits, vi, nil } return nil, nil, fmt.Errorf("No encoding found to encode \"%s\"", content) } barcode-1.0.1/qr/automatic_test.go000066400000000000000000000014461343272050500171140ustar00rootroot00000000000000package qr import ( "bytes" "testing" ) func Test_AutomaticEncoding(t *testing.T) { tests := map[string]encodeFn{ "0123456789": Numeric.getEncoder(), "ALPHA NUMERIC": AlphaNumeric.getEncoder(), "unicode encoing": Unicode.getEncoder(), "very long unicode encoding" + makeString(3000, "A"): nil, } for str, enc := range tests { testValue, _, _ := Auto.getEncoder()(str, M) if enc != nil { correctValue, _, _ := enc(str, M) if testValue == nil || bytes.Compare(correctValue.GetBytes(), testValue.GetBytes()) != 0 { t.Errorf("wrong encoding used for '%s'", str) } } else { if testValue != nil { t.Errorf("wrong encoding used for '%s'", str) } } } } barcode-1.0.1/qr/blocks.go000066400000000000000000000033701343272050500153420ustar00rootroot00000000000000package qr type block struct { data []byte ecc []byte } type blockList []*block func splitToBlocks(data <-chan byte, vi *versionInfo) blockList { result := make(blockList, vi.NumberOfBlocksInGroup1+vi.NumberOfBlocksInGroup2) for b := 0; b < int(vi.NumberOfBlocksInGroup1); b++ { blk := new(block) blk.data = make([]byte, vi.DataCodeWordsPerBlockInGroup1) for cw := 0; cw < int(vi.DataCodeWordsPerBlockInGroup1); cw++ { blk.data[cw] = <-data } blk.ecc = ec.calcECC(blk.data, vi.ErrorCorrectionCodewordsPerBlock) result[b] = blk } for b := 0; b < int(vi.NumberOfBlocksInGroup2); b++ { blk := new(block) blk.data = make([]byte, vi.DataCodeWordsPerBlockInGroup2) for cw := 0; cw < int(vi.DataCodeWordsPerBlockInGroup2); cw++ { blk.data[cw] = <-data } blk.ecc = ec.calcECC(blk.data, vi.ErrorCorrectionCodewordsPerBlock) result[int(vi.NumberOfBlocksInGroup1)+b] = blk } return result } func (bl blockList) interleave(vi *versionInfo) []byte { var maxCodewordCount int if vi.DataCodeWordsPerBlockInGroup1 > vi.DataCodeWordsPerBlockInGroup2 { maxCodewordCount = int(vi.DataCodeWordsPerBlockInGroup1) } else { maxCodewordCount = int(vi.DataCodeWordsPerBlockInGroup2) } resultLen := (vi.DataCodeWordsPerBlockInGroup1+vi.ErrorCorrectionCodewordsPerBlock)*vi.NumberOfBlocksInGroup1 + (vi.DataCodeWordsPerBlockInGroup2+vi.ErrorCorrectionCodewordsPerBlock)*vi.NumberOfBlocksInGroup2 result := make([]byte, 0, resultLen) for i := 0; i < maxCodewordCount; i++ { for b := 0; b < len(bl); b++ { if len(bl[b].data) > i { result = append(result, bl[b].data[i]) } } } for i := 0; i < int(vi.ErrorCorrectionCodewordsPerBlock); i++ { for b := 0; b < len(bl); b++ { result = append(result, bl[b].ecc[i]) } } return result } barcode-1.0.1/qr/blocks_test.go000066400000000000000000000044341343272050500164030ustar00rootroot00000000000000package qr import ( "bytes" "testing" ) func Test_Blocks(t *testing.T) { byteIt := make(chan byte) go func() { for _, b := range []byte{67, 85, 70, 134, 87, 38, 85, 194, 119, 50, 6, 18, 6, 103, 38, 246, 246, 66, 7, 118, 134, 242, 7, 38, 86, 22, 198, 199, 146, 6, 182, 230, 247, 119, 50, 7, 118, 134, 87, 38, 82, 6, 134, 151, 50, 7, 70, 247, 118, 86, 194, 6, 151, 50, 16, 236, 17, 236, 17, 236, 17, 236} { byteIt <- b } close(byteIt) }() vi := &versionInfo{5, Q, 18, 2, 15, 2, 16} data := splitToBlocks(byteIt, vi).interleave(vi) if bytes.Compare(data, []byte{67, 246, 182, 70, 85, 246, 230, 247, 70, 66, 247, 118, 134, 7, 119, 86, 87, 118, 50, 194, 38, 134, 7, 6, 85, 242, 118, 151, 194, 7, 134, 50, 119, 38, 87, 16, 50, 86, 38, 236, 6, 22, 82, 17, 18, 198, 6, 236, 6, 199, 134, 17, 103, 146, 151, 236, 38, 6, 50, 17, 7, 236, 213, 87, 148, 235, 199, 204, 116, 159, 11, 96, 177, 5, 45, 60, 212, 173, 115, 202, 76, 24, 247, 182, 133, 147, 241, 124, 75, 59, 223, 157, 242, 33, 229, 200, 238, 106, 248, 134, 76, 40, 154, 27, 195, 255, 117, 129, 230, 172, 154, 209, 189, 82, 111, 17, 10, 2, 86, 163, 108, 131, 161, 163, 240, 32, 111, 120, 192, 178, 39, 133, 141, 236}) != 0 { t.Fail() } byteIt2 := make(chan byte) go func() { for _, b := range []byte{67, 85, 70, 134, 87, 38, 85, 194, 119, 50, 6, 18, 6, 103, 38, 246, 246, 66, 7, 118, 134, 242, 7, 38, 86, 22, 198, 199, 146, 6, 182, 230, 247, 119, 50, 7, 118, 134, 87, 38, 82, 6, 134, 151, 50, 7, 70, 247, 118, 86, 194, 6, 151, 50, 16, 236, 17, 236, 17, 236, 17, 236} { byteIt2 <- b } close(byteIt2) }() vi = &versionInfo{5, Q, 18, 2, 16, 2, 15} data = splitToBlocks(byteIt2, vi).interleave(vi) if bytes.Compare(data, []byte{67, 246, 247, 247, 85, 66, 119, 118, 70, 7, 50, 86, 134, 118, 7, 194, 87, 134, 118, 6, 38, 242, 134, 151, 85, 7, 87, 50, 194, 38, 38, 16, 119, 86, 82, 236, 50, 22, 6, 17, 6, 198, 134, 236, 18, 199, 151, 17, 6, 146, 50, 236, 103, 6, 7, 17, 38, 182, 70, 236, 246, 230, 71, 101, 27, 62, 13, 91, 166, 86, 138, 16, 78, 229, 102, 11, 199, 107, 2, 182, 132, 103, 89, 66, 136, 69, 78, 255, 116, 129, 126, 163, 219, 234, 158, 216, 42, 234, 97, 62, 186, 59, 123, 148, 220, 191, 254, 145, 82, 95, 129, 79, 236, 254, 30, 174, 228, 50, 181, 110, 150, 205, 34, 235, 242, 0, 115, 147, 58, 243, 28, 140, 221, 219}) != 0 { t.Fail() } } barcode-1.0.1/qr/encoder.go000066400000000000000000000362071343272050500155110ustar00rootroot00000000000000// Package qr can be used to create QR barcodes. package qr import ( "image" "github.com/boombuler/barcode" "github.com/boombuler/barcode/utils" ) type encodeFn func(content string, eccLevel ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) // Encoding mode for QR Codes. type Encoding byte const ( // Auto will choose ths best matching encoding Auto Encoding = iota // Numeric encoding only encodes numbers [0-9] Numeric // AlphaNumeric encoding only encodes uppercase letters, numbers and [Space], $, %, *, +, -, ., /, : AlphaNumeric // Unicode encoding encodes the string as utf-8 Unicode // only for testing purpose unknownEncoding ) func (e Encoding) getEncoder() encodeFn { switch e { case Auto: return encodeAuto case Numeric: return encodeNumeric case AlphaNumeric: return encodeAlphaNumeric case Unicode: return encodeUnicode } return nil } func (e Encoding) String() string { switch e { case Auto: return "Auto" case Numeric: return "Numeric" case AlphaNumeric: return "AlphaNumeric" case Unicode: return "Unicode" } return "" } // Encode returns a QR barcode with the given content, error correction level and uses the given encoding func Encode(content string, level ErrorCorrectionLevel, mode Encoding) (barcode.Barcode, error) { bits, vi, err := mode.getEncoder()(content, level) if err != nil { return nil, err } blocks := splitToBlocks(bits.IterateBytes(), vi) data := blocks.interleave(vi) result := render(data, vi) result.content = content return result, nil } func render(data []byte, vi *versionInfo) *qrcode { dim := vi.modulWidth() results := make([]*qrcode, 8) for i := 0; i < 8; i++ { results[i] = newBarcode(dim) } occupied := newBarcode(dim) setAll := func(x int, y int, val bool) { occupied.Set(x, y, true) for i := 0; i < 8; i++ { results[i].Set(x, y, val) } } drawFinderPatterns(vi, setAll) drawAlignmentPatterns(occupied, vi, setAll) //Timing Pattern: var i int for i = 0; i < dim; i++ { if !occupied.Get(i, 6) { setAll(i, 6, i%2 == 0) } if !occupied.Get(6, i) { setAll(6, i, i%2 == 0) } } // Dark Module setAll(8, dim-8, true) drawVersionInfo(vi, setAll) drawFormatInfo(vi, -1, occupied.Set) for i := 0; i < 8; i++ { drawFormatInfo(vi, i, results[i].Set) } // Write the data var curBitNo int for pos := range iterateModules(occupied) { var curBit bool if curBitNo < len(data)*8 { curBit = ((data[curBitNo/8] >> uint(7-(curBitNo%8))) & 1) == 1 } else { curBit = false } for i := 0; i < 8; i++ { setMasked(pos.X, pos.Y, curBit, i, results[i].Set) } curBitNo++ } lowestPenalty := ^uint(0) lowestPenaltyIdx := -1 for i := 0; i < 8; i++ { p := results[i].calcPenalty() if p < lowestPenalty { lowestPenalty = p lowestPenaltyIdx = i } } return results[lowestPenaltyIdx] } func setMasked(x, y int, val bool, mask int, set func(int, int, bool)) { switch mask { case 0: val = val != (((y + x) % 2) == 0) break case 1: val = val != ((y % 2) == 0) break case 2: val = val != ((x % 3) == 0) break case 3: val = val != (((y + x) % 3) == 0) break case 4: val = val != (((y/2 + x/3) % 2) == 0) break case 5: val = val != (((y*x)%2)+((y*x)%3) == 0) break case 6: val = val != ((((y*x)%2)+((y*x)%3))%2 == 0) break case 7: val = val != ((((y+x)%2)+((y*x)%3))%2 == 0) } set(x, y, val) } func iterateModules(occupied *qrcode) <-chan image.Point { result := make(chan image.Point) allPoints := make(chan image.Point) go func() { curX := occupied.dimension - 1 curY := occupied.dimension - 1 isUpward := true for true { if isUpward { allPoints <- image.Pt(curX, curY) allPoints <- image.Pt(curX-1, curY) curY-- if curY < 0 { curY = 0 curX -= 2 if curX == 6 { curX-- } if curX < 0 { break } isUpward = false } } else { allPoints <- image.Pt(curX, curY) allPoints <- image.Pt(curX-1, curY) curY++ if curY >= occupied.dimension { curY = occupied.dimension - 1 curX -= 2 if curX == 6 { curX-- } isUpward = true if curX < 0 { break } } } } close(allPoints) }() go func() { for pt := range allPoints { if !occupied.Get(pt.X, pt.Y) { result <- pt } } close(result) }() return result } func drawFinderPatterns(vi *versionInfo, set func(int, int, bool)) { dim := vi.modulWidth() drawPattern := func(xoff int, yoff int) { for x := -1; x < 8; x++ { for y := -1; y < 8; y++ { val := (x == 0 || x == 6 || y == 0 || y == 6 || (x > 1 && x < 5 && y > 1 && y < 5)) && (x <= 6 && y <= 6 && x >= 0 && y >= 0) if x+xoff >= 0 && x+xoff < dim && y+yoff >= 0 && y+yoff < dim { set(x+xoff, y+yoff, val) } } } } drawPattern(0, 0) drawPattern(0, dim-7) drawPattern(dim-7, 0) } func drawAlignmentPatterns(occupied *qrcode, vi *versionInfo, set func(int, int, bool)) { drawPattern := func(xoff int, yoff int) { for x := -2; x <= 2; x++ { for y := -2; y <= 2; y++ { val := x == -2 || x == 2 || y == -2 || y == 2 || (x == 0 && y == 0) set(x+xoff, y+yoff, val) } } } positions := vi.alignmentPatternPlacements() for _, x := range positions { for _, y := range positions { if occupied.Get(x, y) { continue } drawPattern(x, y) } } } var formatInfos = map[ErrorCorrectionLevel]map[int][]bool{ L: { 0: []bool{true, true, true, false, true, true, true, true, true, false, false, false, true, false, false}, 1: []bool{true, true, true, false, false, true, false, true, true, true, true, false, false, true, true}, 2: []bool{true, true, true, true, true, false, true, true, false, true, false, true, false, true, false}, 3: []bool{true, true, true, true, false, false, false, true, false, false, true, true, true, false, true}, 4: []bool{true, true, false, false, true, true, false, false, false, true, false, true, true, true, true}, 5: []bool{true, true, false, false, false, true, true, false, false, false, true, true, false, false, false}, 6: []bool{true, true, false, true, true, false, false, false, true, false, false, false, false, false, true}, 7: []bool{true, true, false, true, false, false, true, false, true, true, true, false, true, true, false}, }, M: { 0: []bool{true, false, true, false, true, false, false, false, false, false, true, false, false, true, false}, 1: []bool{true, false, true, false, false, false, true, false, false, true, false, false, true, false, true}, 2: []bool{true, false, true, true, true, true, false, false, true, true, true, true, true, false, false}, 3: []bool{true, false, true, true, false, true, true, false, true, false, false, true, false, true, true}, 4: []bool{true, false, false, false, true, false, true, true, true, true, true, true, false, false, true}, 5: []bool{true, false, false, false, false, false, false, true, true, false, false, true, true, true, false}, 6: []bool{true, false, false, true, true, true, true, true, false, false, true, false, true, true, true}, 7: []bool{true, false, false, true, false, true, false, true, false, true, false, false, false, false, false}, }, Q: { 0: []bool{false, true, true, false, true, false, true, false, true, false, true, true, true, true, true}, 1: []bool{false, true, true, false, false, false, false, false, true, true, false, true, false, false, false}, 2: []bool{false, true, true, true, true, true, true, false, false, true, true, false, false, false, true}, 3: []bool{false, true, true, true, false, true, false, false, false, false, false, false, true, true, false}, 4: []bool{false, true, false, false, true, false, false, true, false, true, true, false, true, false, false}, 5: []bool{false, true, false, false, false, false, true, true, false, false, false, false, false, true, true}, 6: []bool{false, true, false, true, true, true, false, true, true, false, true, true, false, true, false}, 7: []bool{false, true, false, true, false, true, true, true, true, true, false, true, true, false, true}, }, H: { 0: []bool{false, false, true, false, true, true, false, true, false, false, false, true, false, false, true}, 1: []bool{false, false, true, false, false, true, true, true, false, true, true, true, true, true, false}, 2: []bool{false, false, true, true, true, false, false, true, true, true, false, false, true, true, true}, 3: []bool{false, false, true, true, false, false, true, true, true, false, true, false, false, false, false}, 4: []bool{false, false, false, false, true, true, true, false, true, true, false, false, false, true, false}, 5: []bool{false, false, false, false, false, true, false, false, true, false, true, false, true, false, true}, 6: []bool{false, false, false, true, true, false, true, false, false, false, false, true, true, false, false}, 7: []bool{false, false, false, true, false, false, false, false, false, true, true, true, false, true, true}, }, } func drawFormatInfo(vi *versionInfo, usedMask int, set func(int, int, bool)) { var formatInfo []bool if usedMask == -1 { formatInfo = []bool{true, true, true, true, true, true, true, true, true, true, true, true, true, true, true} // Set all to true cause -1 --> occupied mask. } else { formatInfo = formatInfos[vi.Level][usedMask] } if len(formatInfo) == 15 { dim := vi.modulWidth() set(0, 8, formatInfo[0]) set(1, 8, formatInfo[1]) set(2, 8, formatInfo[2]) set(3, 8, formatInfo[3]) set(4, 8, formatInfo[4]) set(5, 8, formatInfo[5]) set(7, 8, formatInfo[6]) set(8, 8, formatInfo[7]) set(8, 7, formatInfo[8]) set(8, 5, formatInfo[9]) set(8, 4, formatInfo[10]) set(8, 3, formatInfo[11]) set(8, 2, formatInfo[12]) set(8, 1, formatInfo[13]) set(8, 0, formatInfo[14]) set(8, dim-1, formatInfo[0]) set(8, dim-2, formatInfo[1]) set(8, dim-3, formatInfo[2]) set(8, dim-4, formatInfo[3]) set(8, dim-5, formatInfo[4]) set(8, dim-6, formatInfo[5]) set(8, dim-7, formatInfo[6]) set(dim-8, 8, formatInfo[7]) set(dim-7, 8, formatInfo[8]) set(dim-6, 8, formatInfo[9]) set(dim-5, 8, formatInfo[10]) set(dim-4, 8, formatInfo[11]) set(dim-3, 8, formatInfo[12]) set(dim-2, 8, formatInfo[13]) set(dim-1, 8, formatInfo[14]) } } var versionInfoBitsByVersion = map[byte][]bool{ 7: []bool{false, false, false, true, true, true, true, true, false, false, true, false, false, true, false, true, false, false}, 8: []bool{false, false, true, false, false, false, false, true, false, true, true, false, true, true, true, true, false, false}, 9: []bool{false, false, true, false, false, true, true, false, true, false, true, false, false, true, true, false, false, true}, 10: []bool{false, false, true, false, true, false, false, true, false, false, true, true, false, true, false, false, true, true}, 11: []bool{false, false, true, false, true, true, true, false, true, true, true, true, true, true, false, true, true, false}, 12: []bool{false, false, true, true, false, false, false, true, true, true, false, true, true, false, false, false, true, false}, 13: []bool{false, false, true, true, false, true, true, false, false, false, false, true, false, false, false, true, true, true}, 14: []bool{false, false, true, true, true, false, false, true, true, false, false, false, false, false, true, true, false, true}, 15: []bool{false, false, true, true, true, true, true, false, false, true, false, false, true, false, true, false, false, false}, 16: []bool{false, true, false, false, false, false, true, false, true, true, false, true, true, true, true, false, false, false}, 17: []bool{false, true, false, false, false, true, false, true, false, false, false, true, false, true, true, true, false, true}, 18: []bool{false, true, false, false, true, false, true, false, true, false, false, false, false, true, false, true, true, true}, 19: []bool{false, true, false, false, true, true, false, true, false, true, false, false, true, true, false, false, true, false}, 20: []bool{false, true, false, true, false, false, true, false, false, true, true, false, true, false, false, true, true, false}, 21: []bool{false, true, false, true, false, true, false, true, true, false, true, false, false, false, false, false, true, true}, 22: []bool{false, true, false, true, true, false, true, false, false, false, true, true, false, false, true, false, false, true}, 23: []bool{false, true, false, true, true, true, false, true, true, true, true, true, true, false, true, true, false, false}, 24: []bool{false, true, true, false, false, false, true, true, true, false, true, true, false, false, false, true, false, false}, 25: []bool{false, true, true, false, false, true, false, false, false, true, true, true, true, false, false, false, false, true}, 26: []bool{false, true, true, false, true, false, true, true, true, true, true, false, true, false, true, false, true, true}, 27: []bool{false, true, true, false, true, true, false, false, false, false, true, false, false, false, true, true, true, false}, 28: []bool{false, true, true, true, false, false, true, true, false, false, false, false, false, true, true, false, true, false}, 29: []bool{false, true, true, true, false, true, false, false, true, true, false, false, true, true, true, true, true, true}, 30: []bool{false, true, true, true, true, false, true, true, false, true, false, true, true, true, false, true, false, true}, 31: []bool{false, true, true, true, true, true, false, false, true, false, false, true, false, true, false, false, false, false}, 32: []bool{true, false, false, false, false, false, true, false, false, true, true, true, false, true, false, true, false, true}, 33: []bool{true, false, false, false, false, true, false, true, true, false, true, true, true, true, false, false, false, false}, 34: []bool{true, false, false, false, true, false, true, false, false, false, true, false, true, true, true, false, true, false}, 35: []bool{true, false, false, false, true, true, false, true, true, true, true, false, false, true, true, true, true, true}, 36: []bool{true, false, false, true, false, false, true, false, true, true, false, false, false, false, true, false, true, true}, 37: []bool{true, false, false, true, false, true, false, true, false, false, false, false, true, false, true, true, true, false}, 38: []bool{true, false, false, true, true, false, true, false, true, false, false, true, true, false, false, true, false, false}, 39: []bool{true, false, false, true, true, true, false, true, false, true, false, true, false, false, false, false, false, true}, 40: []bool{true, false, true, false, false, false, true, true, false, false, false, true, true, false, true, false, false, true}, } func drawVersionInfo(vi *versionInfo, set func(int, int, bool)) { versionInfoBits, ok := versionInfoBitsByVersion[vi.Version] if ok && len(versionInfoBits) > 0 { for i := 0; i < len(versionInfoBits); i++ { x := (vi.modulWidth() - 11) + i%3 y := i / 3 set(x, y, versionInfoBits[len(versionInfoBits)-i-1]) set(y, x, versionInfoBits[len(versionInfoBits)-i-1]) } } } func addPaddingAndTerminator(bl *utils.BitList, vi *versionInfo) { for i := 0; i < 4 && bl.Len() < vi.totalDataBytes()*8; i++ { bl.AddBit(false) } for bl.Len()%8 != 0 { bl.AddBit(false) } for i := 0; bl.Len() < vi.totalDataBytes()*8; i++ { if i%2 == 0 { bl.AddByte(236) } else { bl.AddByte(17) } } } barcode-1.0.1/qr/encoder_test.go000066400000000000000000000047411343272050500165460ustar00rootroot00000000000000package qr import ( "fmt" "image/png" "os" "testing" "github.com/boombuler/barcode" ) type test struct { Text string Mode Encoding ECL ErrorCorrectionLevel Result string } var tests = []test{ test{ Text: "hello world", Mode: Unicode, ECL: H, Result: ` +++++++.+.+.+...+.+++++++ +.....+.++...+++..+.....+ +.+++.+.+.+.++.++.+.+++.+ +.+++.+....++.++..+.+++.+ +.+++.+..+...++.+.+.+++.+ +.....+.+..+..+++.+.....+ +++++++.+.+.+.+.+.+++++++ ........++..+..+......... ..+++.+.+++.+.++++++..+++ +++..+..+...++.+...+..+.. +...+.++++....++.+..++.++ ++.+.+.++...+...+.+....++ ..+..+++.+.+++++.++++++++ +.+++...+..++..++..+..+.. +.....+..+.+.....+++++.++ +.+++.....+...+.+.+++...+ +.+..+++...++.+.+++++++.. ........+....++.+...+.+.. +++++++......++++.+.+.+++ +.....+....+...++...++.+. +.+++.+.+.+...+++++++++.. +.+++.+.++...++...+.++..+ +.+++.+.++.+++++..++.+..+ +.....+..+++..++.+.++...+ +++++++....+..+.+..+..+++`, }, } func Test_GetUnknownEncoder(t *testing.T) { if unknownEncoding.getEncoder() != nil { t.Fail() } } func Test_EncodingStringer(t *testing.T) { tests := map[Encoding]string{ Auto: "Auto", Numeric: "Numeric", AlphaNumeric: "AlphaNumeric", Unicode: "Unicode", unknownEncoding: "", } for enc, str := range tests { if enc.String() != str { t.Fail() } } } func Test_InvalidEncoding(t *testing.T) { _, err := Encode("hello world", H, Numeric) if err == nil { t.Fail() } } func imgStrToBools(str string) []bool { res := make([]bool, 0, len(str)) for _, r := range str { if r == '+' { res = append(res, true) } else if r == '.' { res = append(res, false) } } return res } func Test_Encode(t *testing.T) { for _, tst := range tests { res, err := Encode(tst.Text, tst.ECL, tst.Mode) if err != nil { t.Error(err) } qrCode, ok := res.(*qrcode) if !ok { t.Fail() } testRes := imgStrToBools(tst.Result) if (qrCode.dimension * qrCode.dimension) != len(testRes) { t.Fail() } t.Logf("dim %d", qrCode.dimension) for i := 0; i < len(testRes); i++ { x := i % qrCode.dimension y := i / qrCode.dimension if qrCode.Get(x, y) != testRes[i] { t.Errorf("Failed at index %d", i) } } } } func ExampleEncode() { f, _ := os.Create("qrcode.png") defer f.Close() qrcode, err := Encode("hello world", L, Auto) if err != nil { fmt.Println(err) } else { qrcode, err = barcode.Scale(qrcode, 100, 100) if err != nil { fmt.Println(err) } else { png.Encode(f, qrcode) } } } barcode-1.0.1/qr/errorcorrection.go000066400000000000000000000011771343272050500173110ustar00rootroot00000000000000package qr import ( "github.com/boombuler/barcode/utils" ) type errorCorrection struct { rs *utils.ReedSolomonEncoder } var ec = newErrorCorrection() func newErrorCorrection() *errorCorrection { fld := utils.NewGaloisField(285, 256, 0) return &errorCorrection{utils.NewReedSolomonEncoder(fld)} } func (ec *errorCorrection) calcECC(data []byte, eccCount byte) []byte { dataInts := make([]int, len(data)) for i := 0; i < len(data); i++ { dataInts[i] = int(data[i]) } res := ec.rs.Encode(dataInts, int(eccCount)) result := make([]byte, len(res)) for i := 0; i < len(res); i++ { result[i] = byte(res[i]) } return result } barcode-1.0.1/qr/errorcorrection_test.go000066400000000000000000000236551343272050500203550ustar00rootroot00000000000000package qr import ( "bytes" "testing" ) func Test_ErrorCorrection(t *testing.T) { doTest := func(b []byte, ecc []byte) { cnt := byte(len(ecc)) res := ec.calcECC(b, cnt) if bytes.Compare(res, ecc) != 0 { t.Errorf("ECC error!\nGot: %v\nExpected:%v", res, ecc) } } // Issue #5 doTest([]byte{66, 196, 148, 21, 99, 19, 151, 151, 53, 149, 54, 195, 4, 133, 87, 84, 115, 85, 22, 148, 52, 71, 102, 68, 134, 182, 247, 119, 22, 68, 117, 134, 35, 4, 134, 38, 21, 84, 21, 117, 87, 164, 135, 115, 211, 208, 236, 17, 236, 17, 236, 17, 236, 17, 236}, []byte{187, 187, 171, 253, 164, 129, 104, 133, 3, 75, 87, 98, 241, 146, 138}) // Other tests doTest([]byte{17, 168, 162, 241, 255, 205, 240, 179, 88, 101, 71, 130, 2, 54, 147, 111, 232, 58, 202, 171, 85, 22, 229, 187}, []byte{30, 142, 171, 131, 189}) doTest([]byte{36, 153, 55, 100, 228, 252, 0, 35, 85, 7, 237, 117, 182, 73, 83, 244, 8, 64, 55, 252, 200, 250, 72, 92, 97, 125, 96}, []byte{129, 124, 218, 148, 49, 108, 68, 255, 58, 212, 56, 60, 142, 45, 216, 124, 253, 214, 206, 208, 145, 169, 43}) doTest([]byte{250, 195, 230, 128, 31, 168, 86, 123, 244, 129, 74, 130, 222, 225, 140, 129, 114, 132, 128, 88, 96, 13, 165, 132, 116, 22, 42, 81, 219, 3, 102, 156, 69, 70, 90, 68, 7, 245, 150, 160, 252, 121, 20}, []byte{124, 23, 233, 71, 200, 211, 54, 141, 10, 23, 206, 147, 116, 35, 45, 218, 158, 193, 80, 194, 129, 147, 8, 78, 229, 112, 89, 161, 167, 203, 11, 245, 186, 187, 17, 7, 175}) doTest([]byte{121, 234, 24, 188, 218, 238, 248, 223, 98, 124, 237, 30, 98, 12, 9, 126, 5, 160, 240, 27, 174, 60, 152, 134, 71, 122, 125, 238, 223, 91, 231, 248, 230, 152, 250, 44, 17, 149, 0, 20, 109, 188, 227, 202}, []byte{209, 71, 225, 216, 240, 127, 111, 98, 194, 133, 114, 63, 35, 167, 184, 4, 209, 211, 40, 14, 74, 37, 21, 76, 95, 206, 90, 152, 110, 64, 6, 92, 80, 255, 127, 35, 111, 25, 1, 73}) doTest([]byte{165, 233, 141, 34, 247, 216, 35, 163, 61, 61, 81, 146, 116, 96, 113, 10, 0, 6, 148, 244, 55, 201, 17, 220, 109, 111}, []byte{93, 173, 231, 160}) doTest([]byte{173, 242, 89, 205, 24, 33, 213, 147, 96, 189, 100, 15, 213, 67, 91, 189, 218, 127, 32, 160, 162, 99, 187, 221, 53, 121, 238, 219, 215, 176, 181, 135, 56, 71, 246, 74, 228}, []byte{194, 130, 43, 168, 223, 144, 223, 49, 5, 162, 62, 218, 50, 205, 249, 84, 188, 25, 109, 110, 49, 224, 194, 244, 83, 221, 236, 71, 197, 159, 182}) doTest([]byte{82, 138, 221, 169, 67, 161, 132, 31, 243, 110, 83, 1, 238, 79, 255, 57, 74, 54, 123, 151, 159, 50, 250, 188, 176, 8, 221, 215, 141, 77, 16}, []byte{197, 122, 225, 65, 40, 69, 153, 100, 73, 245, 150, 213, 104, 127, 3}) doTest([]byte{5, 206, 21, 196, 185, 120, 60, 177, 90, 251, 109, 131, 174, 199, 55, 56, 14, 171, 19, 104, 236, 218, 31, 144, 33, 249, 58, 195, 173, 145, 166, 93, 122, 171, 232, 128, 233, 116, 144, 189, 62, 230, 68, 55, 140, 56, 1, 65, 165, 158, 127}, []byte{73, 141, 230, 252, 225, 173, 251, 194, 150, 98, 141, 241, 246, 11, 16, 8, 42}) doTest([]byte{112, 106, 43, 174, 133, 163, 192, 61, 121, 3, 200, 84, 15, 9, 3, 222, 183, 78, 153, 26, 85, 41, 5, 149, 232, 3, 233, 247, 249, 29, 15, 18, 4, 96, 9, 64, 188, 210}, []byte{16, 254, 143, 110, 63, 167, 213, 242, 95, 78, 215, 145, 231, 59, 158, 36, 149, 247, 123, 114, 247, 202, 15, 56, 229, 163, 186, 73, 82, 230, 111, 108, 111, 182, 193, 46, 116}) doTest([]byte{208, 128, 197, 227, 124, 226, 125, 46, 253, 98, 238, 80, 229, 134, 167, 70, 101, 150, 198, 130, 185, 200, 68, 91}, []byte{229, 167, 187, 39, 92, 90, 210, 25, 206, 237, 90, 194, 206, 39, 2, 11, 78, 48, 247}) doTest([]byte{79, 175, 255, 194, 34, 229, 234, 200, 74, 213, 100, 33, 24, 5, 133, 186, 249, 151, 46, 190, 44, 126, 184, 195, 219, 37, 11, 225, 23, 8, 59, 106, 239, 198, 146, 205, 47, 59, 63, 9, 102, 29, 60, 209, 226, 67, 126, 193, 252, 255, 206, 172, 44, 53, 137, 209, 246}, []byte{237, 8, 12, 44, 90, 243, 24, 100, 123, 216, 185, 91, 182, 60, 9, 145, 126, 254, 139, 24, 211, 150, 219, 28, 138, 197, 13, 109, 227, 31, 60, 128, 237, 181, 183, 2, 138, 232, 112, 5}) doTest([]byte{253, 217, 8, 176, 66, 153, 249, 49, 82, 114, 184, 139, 190, 87}, []byte{28, 55, 193, 193, 179, 246, 222, 5, 95, 96, 13, 242}) doTest([]byte{15, 65, 231, 224, 151, 167, 74, 228, 23}, []byte{200, 90, 82}) doTest([]byte{61, 186, 61, 193, 215, 243, 84, 66, 48, 93, 108, 249, 55, 232}, []byte{0, 180, 53, 152, 134, 252, 165, 168}) doTest([]byte{78, 68, 116, 15, 85}, []byte{36}) doTest([]byte{122, 143}, []byte{245}) doTest([]byte{78, 85, 143, 35}, []byte{226, 85}) doTest([]byte{11, 188, 118, 21, 177, 224, 151, 105, 21, 245, 251, 162, 72, 175, 248, 134, 123, 251, 160, 163, 42, 57, 53, 222, 195, 49, 199, 151, 5, 236, 160, 57, 212, 241, 44, 43}, []byte{186, 106}) doTest([]byte{157, 99, 220, 166, 63, 18, 225, 215, 71, 95, 99, 200, 218, 147, 131, 245, 222, 209, 135, 152, 82, 128, 24, 0, 100, 40, 84, 193, 205, 86, 130, 204, 235, 100, 94, 61}, []byte{41, 171, 66, 233}) doTest([]byte{249, 34, 253, 235, 233, 104, 52, 60, 17, 13, 182, 223, 19, 91, 164, 2, 196, 29, 74, 219, 65, 23, 190, 31, 10, 241, 221, 150, 221, 118, 53, 69, 45, 90, 215, 100, 155, 102, 150, 176, 203, 39, 22, 70, 10, 238}, []byte{161, 49, 179, 149, 178, 146, 208, 144, 19, 158, 180, 152, 243, 138, 143, 243, 82, 112, 229, 10, 113, 255, 139, 246}) doTest([]byte{39, 232, 159, 64, 242, 235, 66, 226, 100, 221, 225, 247, 139, 157, 95, 155}, []byte{41, 9, 244}) doTest([]byte{177, 185, 131, 64, 103, 93, 134, 153, 15, 26, 0, 119, 21, 27, 174, 181, 111, 245, 214, 244, 83, 66, 24, 244, 255, 189, 133, 158, 37, 46, 199, 123, 110, 153, 61, 137, 163, 231, 129, 65, 186, 89, 219, 39, 226, 236, 199, 197, 73, 213}, []byte{37, 59, 125, 211, 249, 177, 107, 79, 107, 47, 242, 168, 49, 38, 168, 198, 199, 91, 212, 22, 107, 244}) doTest([]byte{196, 226, 29, 110, 161, 143, 64, 169, 216, 231, 115}, []byte{253, 93, 218, 129, 37}) doTest([]byte{133, 8, 124, 221, 36, 17, 135, 115, 149, 58, 250, 103, 241, 18, 19, 246, 191, 85, 80, 255, 93, 182, 140, 123, 206, 232, 20, 166, 216, 105, 210, 229, 249, 212, 93, 227, 75, 231, 36, 195, 166, 246, 47, 168, 35, 7, 176, 124, 44, 179, 24, 145}, []byte{78, 57, 134, 181, 215, 149, 111, 51, 172, 58, 114, 3, 140, 186, 126, 40, 190}) doTest([]byte{245, 206, 124, 0, 15, 59, 253, 225, 155}, []byte{65, 14, 188, 213, 18, 113, 161, 16}) doTest([]byte{20, 109, 28, 180, 48, 170, 216, 48, 140, 89, 103}, []byte{193, 147, 50, 209, 160}) doTest([]byte{87, 198, 56, 151, 121, 37, 81, 64, 193, 24, 222, 142, 102, 74, 216, 233, 198, 197, 90, 4, 65, 14, 154, 147, 200, 252, 8, 64, 97, 150, 136, 141}, []byte{231, 190, 32, 90, 100, 40, 41, 103, 200, 200, 243, 75, 177, 7, 93, 28, 83, 47, 188, 236, 20, 95, 69, 104, 155, 102, 110, 197}) doTest([]byte{168, 72, 2, 101, 103, 118, 218, 38, 82, 85, 62, 37, 201, 96, 255, 71, 198}, []byte{129, 33, 28, 228, 195, 120, 101, 46, 119, 126}) doTest([]byte{130, 162, 73, 44, 165, 207, 124, 28, 17, 223, 43, 143, 81, 70, 205, 161, 143, 230, 97, 94, 228, 41, 26, 187, 69, 85, 162, 51, 168, 64, 26, 207, 245, 128}, []byte{6, 171}) doTest([]byte{95, 28, 93, 149, 234, 89, 201, 71, 39, 197, 236, 223, 251, 190, 112, 96, 101, 53, 40, 88, 136, 141, 230, 80, 45, 73, 116, 208, 197, 91, 154, 209, 128, 214, 66, 114, 137, 204, 115, 139, 96, 211, 148, 127, 104, 194}, []byte{10, 102, 57, 95, 61, 212, 130, 71, 74, 58, 82, 115, 238, 213, 251, 184, 203, 250, 55, 186, 37, 16, 71, 247, 146, 194, 74, 208, 221, 6, 81, 172, 204, 73, 102, 40, 247, 174, 213, 37, 225, 246, 8, 58}) doTest([]byte{207, 185, 106, 191, 87, 109, 110, 210, 54, 12, 103, 161, 228}, []byte{214, 138, 159, 195, 154, 236, 33, 243, 53, 79, 227}) doTest([]byte{203, 43, 26, 94, 37, 123, 254, 215, 153, 193, 157, 248, 180, 249, 103, 232, 107, 17, 138, 0, 11, 240, 218, 122, 19, 103, 112, 60, 125, 100, 209, 166, 103, 81, 200, 84, 77, 100, 18, 110, 209, 225, 209, 254, 185, 116, 186, 216, 206, 36, 252, 144, 90, 247, 117, 219, 81, 160}, []byte{185, 176, 106, 253, 76, 153, 185, 211, 187, 153, 210, 31, 99, 4, 46, 145, 221, 99, 236, 19, 126, 138, 66, 26, 40, 217, 170, 217, 147}) doTest([]byte{11, 193, 90, 52, 239, 247, 144, 99, 48, 19, 154, 6, 255, 28, 47, 41, 30, 220}, []byte{235, 165, 125, 82, 28, 116, 21, 133, 243, 222, 241, 20, 134}) doTest([]byte{173, 151, 109, 88, 104, 65, 76, 111, 219, 237, 2, 173, 25, 84, 98, 16, 135, 157, 14, 194, 228, 86, 167, 187, 137, 245, 144, 61, 200, 76, 188, 117, 223, 172, 16, 116, 84, 1, 203, 173, 170, 32, 135, 67, 16}, []byte{150, 31, 11, 211, 82, 221, 251, 84, 254, 121, 68, 34, 211, 142, 197, 246, 138, 204, 60, 197, 210, 238, 142, 234, 187, 200, 179, 228}) doTest([]byte{171, 185, 30, 162, 129, 205, 254, 186, 86, 239, 178, 206, 115, 177, 14, 166, 143, 48, 141, 205, 109, 67, 238, 187, 134, 210, 96, 23, 195, 206, 100, 171, 156, 8, 229, 131, 169, 169, 59, 167, 224, 241, 185, 132, 162, 50, 87, 252, 156, 122, 248, 19, 130, 31, 127}, []byte{62, 42, 216, 109, 23, 176, 255, 137, 139, 90, 7, 186, 175, 243, 160, 206, 37, 94, 157, 217, 11, 169, 126, 41, 73, 133, 212, 232, 249, 117, 70, 147, 137, 156, 43, 243, 234, 155, 94, 38, 59, 211, 218, 165, 3, 33, 231, 237, 92, 16, 128}) doTest([]byte{98, 28, 174, 108, 231, 247, 135, 139, 6, 50, 107, 203, 138, 252, 229, 245, 230, 236, 124, 138, 105, 25, 83, 122}, []byte{97, 214, 25, 2, 14, 48, 65, 212, 241, 200, 81, 57, 176, 59, 16, 55, 20, 91, 66}) doTest([]byte{73, 214, 80, 41, 125, 136, 126, 184, 70, 141, 140, 58, 249, 250, 49, 249, 155, 0, 236, 49, 17, 125, 18, 29}, []byte{128, 16, 47, 235, 125, 128, 97, 245, 177, 210, 219, 195}) doTest([]byte{3, 220, 98, 73, 200, 52, 8, 107, 173, 177, 58, 221, 180, 226, 76, 210, 182, 88, 104, 171, 243, 129, 88, 112, 126, 83, 141, 50, 106, 204, 195, 51, 141, 75, 132, 161}, []byte{110, 178, 213, 174, 1, 241, 95}) doTest([]byte{196, 88, 50, 142, 76, 128, 190, 189, 76, 9, 228, 62, 198, 186, 180, 240, 62, 130, 132, 242}, []byte{244, 89, 17, 143, 3, 180, 150, 242, 167, 214, 209, 133, 120, 213, 173, 59, 25, 158, 251}) doTest([]byte{166, 214, 1, 225, 237, 7, 80, 104, 94, 170, 125, 184, 148, 16, 121, 101, 52, 216, 177, 192, 6, 132, 77, 44, 5, 9, 126, 156, 12, 2, 29, 99, 51, 78, 177, 92, 140, 107, 146, 183, 109, 227, 171, 57, 193, 14, 37}, []byte{245, 46, 189, 11, 202, 195, 89, 53, 215, 172, 132, 196, 145, 141, 239, 160, 242, 7, 85, 251, 193, 85}) } barcode-1.0.1/qr/numeric.go000066400000000000000000000021601343272050500155230ustar00rootroot00000000000000package qr import ( "errors" "fmt" "strconv" "github.com/boombuler/barcode/utils" ) func encodeNumeric(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) { contentBitCount := (len(content) / 3) * 10 switch len(content) % 3 { case 1: contentBitCount += 4 case 2: contentBitCount += 7 } vi := findSmallestVersionInfo(ecl, numericMode, contentBitCount) if vi == nil { return nil, nil, errors.New("To much data to encode") } res := new(utils.BitList) res.AddBits(int(numericMode), 4) res.AddBits(len(content), vi.charCountBits(numericMode)) for pos := 0; pos < len(content); pos += 3 { var curStr string if pos+3 <= len(content) { curStr = content[pos : pos+3] } else { curStr = content[pos:] } i, err := strconv.Atoi(curStr) if err != nil || i < 0 { return nil, nil, fmt.Errorf("\"%s\" can not be encoded as %s", content, Numeric) } var bitCnt byte switch len(curStr) % 3 { case 0: bitCnt = 10 case 1: bitCnt = 4 break case 2: bitCnt = 7 break } res.AddBits(i, bitCnt) } addPaddingAndTerminator(res, vi) return res, vi, nil } barcode-1.0.1/qr/numeric_test.go000066400000000000000000000014171343272050500165660ustar00rootroot00000000000000package qr import ( "bytes" "testing" ) func Test_NumericEncoding(t *testing.T) { encode := Numeric.getEncoder() x, vi, err := encode("01234567", H) if x == nil || vi == nil || vi.Version != 1 || bytes.Compare(x.GetBytes(), []byte{16, 32, 12, 86, 97, 128, 236, 17, 236}) != 0 { t.Error("\"01234567\" failed to encode") } x, vi, err = encode("0123456789012345", H) if x == nil || vi == nil || vi.Version != 1 || bytes.Compare(x.GetBytes(), []byte{16, 64, 12, 86, 106, 110, 20, 234, 80}) != 0 { t.Error("\"0123456789012345\" failed to encode") } x, vi, err = encode("foo", H) if err == nil { t.Error("Numeric encoding should not be able to encode \"foo\"") } x, vi, err = encode(makeString(14297, "1"), H) if x != nil || vi != nil || err == nil { t.Fail() } } barcode-1.0.1/qr/qrcode.go000066400000000000000000000063551343272050500153500ustar00rootroot00000000000000package qr import ( "image" "image/color" "math" "github.com/boombuler/barcode" "github.com/boombuler/barcode/utils" ) type qrcode struct { dimension int data *utils.BitList content string } func (qr *qrcode) Content() string { return qr.content } func (qr *qrcode) Metadata() barcode.Metadata { return barcode.Metadata{barcode.TypeQR, 2} } func (qr *qrcode) ColorModel() color.Model { return color.Gray16Model } func (qr *qrcode) Bounds() image.Rectangle { return image.Rect(0, 0, qr.dimension, qr.dimension) } func (qr *qrcode) At(x, y int) color.Color { if qr.Get(x, y) { return color.Black } return color.White } func (qr *qrcode) Get(x, y int) bool { return qr.data.GetBit(x*qr.dimension + y) } func (qr *qrcode) Set(x, y int, val bool) { qr.data.SetBit(x*qr.dimension+y, val) } func (qr *qrcode) calcPenalty() uint { return qr.calcPenaltyRule1() + qr.calcPenaltyRule2() + qr.calcPenaltyRule3() + qr.calcPenaltyRule4() } func (qr *qrcode) calcPenaltyRule1() uint { var result uint for x := 0; x < qr.dimension; x++ { checkForX := false var cntX uint checkForY := false var cntY uint for y := 0; y < qr.dimension; y++ { if qr.Get(x, y) == checkForX { cntX++ } else { checkForX = !checkForX if cntX >= 5 { result += cntX - 2 } cntX = 1 } if qr.Get(y, x) == checkForY { cntY++ } else { checkForY = !checkForY if cntY >= 5 { result += cntY - 2 } cntY = 1 } } if cntX >= 5 { result += cntX - 2 } if cntY >= 5 { result += cntY - 2 } } return result } func (qr *qrcode) calcPenaltyRule2() uint { var result uint for x := 0; x < qr.dimension-1; x++ { for y := 0; y < qr.dimension-1; y++ { check := qr.Get(x, y) if qr.Get(x, y+1) == check && qr.Get(x+1, y) == check && qr.Get(x+1, y+1) == check { result += 3 } } } return result } func (qr *qrcode) calcPenaltyRule3() uint { pattern1 := []bool{true, false, true, true, true, false, true, false, false, false, false} pattern2 := []bool{false, false, false, false, true, false, true, true, true, false, true} var result uint for x := 0; x <= qr.dimension-len(pattern1); x++ { for y := 0; y < qr.dimension; y++ { pattern1XFound := true pattern2XFound := true pattern1YFound := true pattern2YFound := true for i := 0; i < len(pattern1); i++ { iv := qr.Get(x+i, y) if iv != pattern1[i] { pattern1XFound = false } if iv != pattern2[i] { pattern2XFound = false } iv = qr.Get(y, x+i) if iv != pattern1[i] { pattern1YFound = false } if iv != pattern2[i] { pattern2YFound = false } } if pattern1XFound || pattern2XFound { result += 40 } if pattern1YFound || pattern2YFound { result += 40 } } } return result } func (qr *qrcode) calcPenaltyRule4() uint { totalNum := qr.data.Len() trueCnt := 0 for i := 0; i < totalNum; i++ { if qr.data.GetBit(i) { trueCnt++ } } percDark := float64(trueCnt) * 100 / float64(totalNum) floor := math.Abs(math.Floor(percDark/5) - 10) ceil := math.Abs(math.Ceil(percDark/5) - 10) return uint(math.Min(floor, ceil) * 10) } func newBarcode(dim int) *qrcode { res := new(qrcode) res.dimension = dim res.data = utils.NewBitList(dim * dim) return res } barcode-1.0.1/qr/qrcode_test.go000066400000000000000000000044611343272050500164030ustar00rootroot00000000000000package qr import ( "image/color" "testing" ) func Test_NewQRCode(t *testing.T) { bc := newBarcode(2) if bc == nil { t.Fail() } if bc.data.Len() != 4 { t.Fail() } if bc.dimension != 2 { t.Fail() } } func Test_QRBasics(t *testing.T) { qr := newBarcode(10) if qr.ColorModel() != color.Gray16Model { t.Fail() } code, _ := Encode("test", L, Unicode) if code.Content() != "test" { t.Fail() } if code.Metadata().Dimensions != 2 { t.Fail() } bounds := code.Bounds() if bounds.Min.X != 0 || bounds.Min.Y != 0 || bounds.Max.X != 21 || bounds.Max.Y != 21 { t.Fail() } if code.At(0, 0) != color.Black || code.At(0, 7) != color.White { t.Fail() } qr = code.(*qrcode) if !qr.Get(0, 0) || qr.Get(0, 7) { t.Fail() } sum := qr.calcPenaltyRule1() + qr.calcPenaltyRule2() + qr.calcPenaltyRule3() + qr.calcPenaltyRule4() if qr.calcPenalty() != sum { t.Fail() } } func Test_Penalty1(t *testing.T) { qr := newBarcode(7) if qr.calcPenaltyRule1() != 70 { t.Fail() } qr.Set(0, 0, true) if qr.calcPenaltyRule1() != 68 { t.Fail() } qr.Set(0, 6, true) if qr.calcPenaltyRule1() != 66 { t.Fail() } } func Test_Penalty2(t *testing.T) { qr := newBarcode(3) if qr.calcPenaltyRule2() != 12 { t.Fail() } qr.Set(0, 0, true) qr.Set(1, 1, true) qr.Set(2, 0, true) if qr.calcPenaltyRule2() != 0 { t.Fail() } qr.Set(1, 1, false) if qr.calcPenaltyRule2() != 6 { t.Fail() } } func Test_Penalty3(t *testing.T) { runTest := func(content string, result uint) { code, _ := Encode(content, L, AlphaNumeric) qr := code.(*qrcode) if qr.calcPenaltyRule3() != result { t.Errorf("Failed Penalty Rule 3 for content \"%s\" got %d but expected %d", content, qr.calcPenaltyRule3(), result) } } runTest("A", 80) runTest("FOO", 40) runTest("0815", 0) } func Test_Penalty4(t *testing.T) { qr := newBarcode(3) if qr.calcPenaltyRule4() != 100 { t.Fail() } qr.Set(0, 0, true) if qr.calcPenaltyRule4() != 70 { t.Fail() } qr.Set(0, 1, true) if qr.calcPenaltyRule4() != 50 { t.Fail() } qr.Set(0, 2, true) if qr.calcPenaltyRule4() != 30 { t.Fail() } qr.Set(1, 0, true) if qr.calcPenaltyRule4() != 10 { t.Fail() } qr.Set(1, 1, true) if qr.calcPenaltyRule4() != 10 { t.Fail() } qr = newBarcode(2) qr.Set(0, 0, true) qr.Set(1, 0, true) if qr.calcPenaltyRule4() != 0 { t.Fail() } } barcode-1.0.1/qr/unicode.go000066400000000000000000000012511343272050500155070ustar00rootroot00000000000000package qr import ( "errors" "github.com/boombuler/barcode/utils" ) func encodeUnicode(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) { data := []byte(content) vi := findSmallestVersionInfo(ecl, byteMode, len(data)*8) if vi == nil { return nil, nil, errors.New("To much data to encode") } // It's not correct to add the unicode bytes to the result directly but most readers can't handle the // required ECI header... res := new(utils.BitList) res.AddBits(int(byteMode), 4) res.AddBits(len(content), vi.charCountBits(byteMode)) for _, b := range data { res.AddByte(b) } addPaddingAndTerminator(res, vi) return res, vi, nil } barcode-1.0.1/qr/unicode_test.go000066400000000000000000000007311343272050500165500ustar00rootroot00000000000000package qr import ( "bytes" "testing" ) func Test_UnicodeEncoding(t *testing.T) { encode := Unicode.getEncoder() x, vi, err := encode("A", H) // 65 if x == nil || vi == nil || vi.Version != 1 || bytes.Compare(x.GetBytes(), []byte{64, 20, 16, 236, 17, 236, 17, 236, 17}) != 0 { t.Errorf("\"A\" failed to encode: %s", err) } _, _, err = encode(makeString(3000, "A"), H) if err == nil { t.Error("Unicode encoding should not be able to encode a 3kb string") } } barcode-1.0.1/qr/versioninfo.go000066400000000000000000000223111343272050500164220ustar00rootroot00000000000000package qr import "math" // ErrorCorrectionLevel indicates the amount of "backup data" stored in the QR code type ErrorCorrectionLevel byte const ( // L recovers 7% of data L ErrorCorrectionLevel = iota // M recovers 15% of data M // Q recovers 25% of data Q // H recovers 30% of data H ) func (ecl ErrorCorrectionLevel) String() string { switch ecl { case L: return "L" case M: return "M" case Q: return "Q" case H: return "H" } return "unknown" } type encodingMode byte const ( numericMode encodingMode = 1 alphaNumericMode encodingMode = 2 byteMode encodingMode = 4 kanjiMode encodingMode = 8 ) type versionInfo struct { Version byte Level ErrorCorrectionLevel ErrorCorrectionCodewordsPerBlock byte NumberOfBlocksInGroup1 byte DataCodeWordsPerBlockInGroup1 byte NumberOfBlocksInGroup2 byte DataCodeWordsPerBlockInGroup2 byte } var versionInfos = []*versionInfo{ &versionInfo{1, L, 7, 1, 19, 0, 0}, &versionInfo{1, M, 10, 1, 16, 0, 0}, &versionInfo{1, Q, 13, 1, 13, 0, 0}, &versionInfo{1, H, 17, 1, 9, 0, 0}, &versionInfo{2, L, 10, 1, 34, 0, 0}, &versionInfo{2, M, 16, 1, 28, 0, 0}, &versionInfo{2, Q, 22, 1, 22, 0, 0}, &versionInfo{2, H, 28, 1, 16, 0, 0}, &versionInfo{3, L, 15, 1, 55, 0, 0}, &versionInfo{3, M, 26, 1, 44, 0, 0}, &versionInfo{3, Q, 18, 2, 17, 0, 0}, &versionInfo{3, H, 22, 2, 13, 0, 0}, &versionInfo{4, L, 20, 1, 80, 0, 0}, &versionInfo{4, M, 18, 2, 32, 0, 0}, &versionInfo{4, Q, 26, 2, 24, 0, 0}, &versionInfo{4, H, 16, 4, 9, 0, 0}, &versionInfo{5, L, 26, 1, 108, 0, 0}, &versionInfo{5, M, 24, 2, 43, 0, 0}, &versionInfo{5, Q, 18, 2, 15, 2, 16}, &versionInfo{5, H, 22, 2, 11, 2, 12}, &versionInfo{6, L, 18, 2, 68, 0, 0}, &versionInfo{6, M, 16, 4, 27, 0, 0}, &versionInfo{6, Q, 24, 4, 19, 0, 0}, &versionInfo{6, H, 28, 4, 15, 0, 0}, &versionInfo{7, L, 20, 2, 78, 0, 0}, &versionInfo{7, M, 18, 4, 31, 0, 0}, &versionInfo{7, Q, 18, 2, 14, 4, 15}, &versionInfo{7, H, 26, 4, 13, 1, 14}, &versionInfo{8, L, 24, 2, 97, 0, 0}, &versionInfo{8, M, 22, 2, 38, 2, 39}, &versionInfo{8, Q, 22, 4, 18, 2, 19}, &versionInfo{8, H, 26, 4, 14, 2, 15}, &versionInfo{9, L, 30, 2, 116, 0, 0}, &versionInfo{9, M, 22, 3, 36, 2, 37}, &versionInfo{9, Q, 20, 4, 16, 4, 17}, &versionInfo{9, H, 24, 4, 12, 4, 13}, &versionInfo{10, L, 18, 2, 68, 2, 69}, &versionInfo{10, M, 26, 4, 43, 1, 44}, &versionInfo{10, Q, 24, 6, 19, 2, 20}, &versionInfo{10, H, 28, 6, 15, 2, 16}, &versionInfo{11, L, 20, 4, 81, 0, 0}, &versionInfo{11, M, 30, 1, 50, 4, 51}, &versionInfo{11, Q, 28, 4, 22, 4, 23}, &versionInfo{11, H, 24, 3, 12, 8, 13}, &versionInfo{12, L, 24, 2, 92, 2, 93}, &versionInfo{12, M, 22, 6, 36, 2, 37}, &versionInfo{12, Q, 26, 4, 20, 6, 21}, &versionInfo{12, H, 28, 7, 14, 4, 15}, &versionInfo{13, L, 26, 4, 107, 0, 0}, &versionInfo{13, M, 22, 8, 37, 1, 38}, &versionInfo{13, Q, 24, 8, 20, 4, 21}, &versionInfo{13, H, 22, 12, 11, 4, 12}, &versionInfo{14, L, 30, 3, 115, 1, 116}, &versionInfo{14, M, 24, 4, 40, 5, 41}, &versionInfo{14, Q, 20, 11, 16, 5, 17}, &versionInfo{14, H, 24, 11, 12, 5, 13}, &versionInfo{15, L, 22, 5, 87, 1, 88}, &versionInfo{15, M, 24, 5, 41, 5, 42}, &versionInfo{15, Q, 30, 5, 24, 7, 25}, &versionInfo{15, H, 24, 11, 12, 7, 13}, &versionInfo{16, L, 24, 5, 98, 1, 99}, &versionInfo{16, M, 28, 7, 45, 3, 46}, &versionInfo{16, Q, 24, 15, 19, 2, 20}, &versionInfo{16, H, 30, 3, 15, 13, 16}, &versionInfo{17, L, 28, 1, 107, 5, 108}, &versionInfo{17, M, 28, 10, 46, 1, 47}, &versionInfo{17, Q, 28, 1, 22, 15, 23}, &versionInfo{17, H, 28, 2, 14, 17, 15}, &versionInfo{18, L, 30, 5, 120, 1, 121}, &versionInfo{18, M, 26, 9, 43, 4, 44}, &versionInfo{18, Q, 28, 17, 22, 1, 23}, &versionInfo{18, H, 28, 2, 14, 19, 15}, &versionInfo{19, L, 28, 3, 113, 4, 114}, &versionInfo{19, M, 26, 3, 44, 11, 45}, &versionInfo{19, Q, 26, 17, 21, 4, 22}, &versionInfo{19, H, 26, 9, 13, 16, 14}, &versionInfo{20, L, 28, 3, 107, 5, 108}, &versionInfo{20, M, 26, 3, 41, 13, 42}, &versionInfo{20, Q, 30, 15, 24, 5, 25}, &versionInfo{20, H, 28, 15, 15, 10, 16}, &versionInfo{21, L, 28, 4, 116, 4, 117}, &versionInfo{21, M, 26, 17, 42, 0, 0}, &versionInfo{21, Q, 28, 17, 22, 6, 23}, &versionInfo{21, H, 30, 19, 16, 6, 17}, &versionInfo{22, L, 28, 2, 111, 7, 112}, &versionInfo{22, M, 28, 17, 46, 0, 0}, &versionInfo{22, Q, 30, 7, 24, 16, 25}, &versionInfo{22, H, 24, 34, 13, 0, 0}, &versionInfo{23, L, 30, 4, 121, 5, 122}, &versionInfo{23, M, 28, 4, 47, 14, 48}, &versionInfo{23, Q, 30, 11, 24, 14, 25}, &versionInfo{23, H, 30, 16, 15, 14, 16}, &versionInfo{24, L, 30, 6, 117, 4, 118}, &versionInfo{24, M, 28, 6, 45, 14, 46}, &versionInfo{24, Q, 30, 11, 24, 16, 25}, &versionInfo{24, H, 30, 30, 16, 2, 17}, &versionInfo{25, L, 26, 8, 106, 4, 107}, &versionInfo{25, M, 28, 8, 47, 13, 48}, &versionInfo{25, Q, 30, 7, 24, 22, 25}, &versionInfo{25, H, 30, 22, 15, 13, 16}, &versionInfo{26, L, 28, 10, 114, 2, 115}, &versionInfo{26, M, 28, 19, 46, 4, 47}, &versionInfo{26, Q, 28, 28, 22, 6, 23}, &versionInfo{26, H, 30, 33, 16, 4, 17}, &versionInfo{27, L, 30, 8, 122, 4, 123}, &versionInfo{27, M, 28, 22, 45, 3, 46}, &versionInfo{27, Q, 30, 8, 23, 26, 24}, &versionInfo{27, H, 30, 12, 15, 28, 16}, &versionInfo{28, L, 30, 3, 117, 10, 118}, &versionInfo{28, M, 28, 3, 45, 23, 46}, &versionInfo{28, Q, 30, 4, 24, 31, 25}, &versionInfo{28, H, 30, 11, 15, 31, 16}, &versionInfo{29, L, 30, 7, 116, 7, 117}, &versionInfo{29, M, 28, 21, 45, 7, 46}, &versionInfo{29, Q, 30, 1, 23, 37, 24}, &versionInfo{29, H, 30, 19, 15, 26, 16}, &versionInfo{30, L, 30, 5, 115, 10, 116}, &versionInfo{30, M, 28, 19, 47, 10, 48}, &versionInfo{30, Q, 30, 15, 24, 25, 25}, &versionInfo{30, H, 30, 23, 15, 25, 16}, &versionInfo{31, L, 30, 13, 115, 3, 116}, &versionInfo{31, M, 28, 2, 46, 29, 47}, &versionInfo{31, Q, 30, 42, 24, 1, 25}, &versionInfo{31, H, 30, 23, 15, 28, 16}, &versionInfo{32, L, 30, 17, 115, 0, 0}, &versionInfo{32, M, 28, 10, 46, 23, 47}, &versionInfo{32, Q, 30, 10, 24, 35, 25}, &versionInfo{32, H, 30, 19, 15, 35, 16}, &versionInfo{33, L, 30, 17, 115, 1, 116}, &versionInfo{33, M, 28, 14, 46, 21, 47}, &versionInfo{33, Q, 30, 29, 24, 19, 25}, &versionInfo{33, H, 30, 11, 15, 46, 16}, &versionInfo{34, L, 30, 13, 115, 6, 116}, &versionInfo{34, M, 28, 14, 46, 23, 47}, &versionInfo{34, Q, 30, 44, 24, 7, 25}, &versionInfo{34, H, 30, 59, 16, 1, 17}, &versionInfo{35, L, 30, 12, 121, 7, 122}, &versionInfo{35, M, 28, 12, 47, 26, 48}, &versionInfo{35, Q, 30, 39, 24, 14, 25}, &versionInfo{35, H, 30, 22, 15, 41, 16}, &versionInfo{36, L, 30, 6, 121, 14, 122}, &versionInfo{36, M, 28, 6, 47, 34, 48}, &versionInfo{36, Q, 30, 46, 24, 10, 25}, &versionInfo{36, H, 30, 2, 15, 64, 16}, &versionInfo{37, L, 30, 17, 122, 4, 123}, &versionInfo{37, M, 28, 29, 46, 14, 47}, &versionInfo{37, Q, 30, 49, 24, 10, 25}, &versionInfo{37, H, 30, 24, 15, 46, 16}, &versionInfo{38, L, 30, 4, 122, 18, 123}, &versionInfo{38, M, 28, 13, 46, 32, 47}, &versionInfo{38, Q, 30, 48, 24, 14, 25}, &versionInfo{38, H, 30, 42, 15, 32, 16}, &versionInfo{39, L, 30, 20, 117, 4, 118}, &versionInfo{39, M, 28, 40, 47, 7, 48}, &versionInfo{39, Q, 30, 43, 24, 22, 25}, &versionInfo{39, H, 30, 10, 15, 67, 16}, &versionInfo{40, L, 30, 19, 118, 6, 119}, &versionInfo{40, M, 28, 18, 47, 31, 48}, &versionInfo{40, Q, 30, 34, 24, 34, 25}, &versionInfo{40, H, 30, 20, 15, 61, 16}, } func (vi *versionInfo) totalDataBytes() int { g1Data := int(vi.NumberOfBlocksInGroup1) * int(vi.DataCodeWordsPerBlockInGroup1) g2Data := int(vi.NumberOfBlocksInGroup2) * int(vi.DataCodeWordsPerBlockInGroup2) return (g1Data + g2Data) } func (vi *versionInfo) charCountBits(m encodingMode) byte { switch m { case numericMode: if vi.Version < 10 { return 10 } else if vi.Version < 27 { return 12 } return 14 case alphaNumericMode: if vi.Version < 10 { return 9 } else if vi.Version < 27 { return 11 } return 13 case byteMode: if vi.Version < 10 { return 8 } return 16 case kanjiMode: if vi.Version < 10 { return 8 } else if vi.Version < 27 { return 10 } return 12 default: return 0 } } func (vi *versionInfo) modulWidth() int { return ((int(vi.Version) - 1) * 4) + 21 } func (vi *versionInfo) alignmentPatternPlacements() []int { if vi.Version == 1 { return make([]int, 0) } first := 6 last := vi.modulWidth() - 7 space := float64(last - first) count := int(math.Ceil(space/28)) + 1 result := make([]int, count) result[0] = first result[len(result)-1] = last if count > 2 { step := int(math.Ceil(float64(last-first) / float64(count-1))) if step%2 == 1 { frac := float64(last-first) / float64(count-1) _, x := math.Modf(frac) if x >= 0.5 { frac = math.Ceil(frac) } else { frac = math.Floor(frac) } if int(frac)%2 == 0 { step-- } else { step++ } } for i := 1; i <= count-2; i++ { result[i] = last - (step * (count - 1 - i)) } } return result } func findSmallestVersionInfo(ecl ErrorCorrectionLevel, mode encodingMode, dataBits int) *versionInfo { dataBits = dataBits + 4 // mode indicator for _, vi := range versionInfos { if vi.Level == ecl { if (vi.totalDataBytes() * 8) >= (dataBits + int(vi.charCountBits(mode))) { return vi } } } return nil } barcode-1.0.1/qr/versioninfo_test.go000066400000000000000000000103261343272050500174640ustar00rootroot00000000000000package qr import "testing" var testvi = &versionInfo{7, M, 0, 1, 10, 2, 5} // Fake versionInfo to run some of the tests func Test_ErrorCorrectionStringer(t *testing.T) { tests := map[ErrorCorrectionLevel]string{ L: "L", M: "M", Q: "Q", H: "H", ErrorCorrectionLevel(99): "unknown", } for ecl, str := range tests { if ecl.String() != str { t.Fail() } } } func Test_CharCountBits(t *testing.T) { v1 := &versionInfo{5, M, 0, 0, 0, 0, 0} v2 := &versionInfo{15, M, 0, 0, 0, 0, 0} v3 := &versionInfo{30, M, 0, 0, 0, 0, 0} if v1.charCountBits(numericMode) != 10 { t.Fail() } if v1.charCountBits(alphaNumericMode) != 9 { t.Fail() } if v1.charCountBits(byteMode) != 8 { t.Fail() } if v1.charCountBits(kanjiMode) != 8 { t.Fail() } if v2.charCountBits(numericMode) != 12 { t.Fail() } if v2.charCountBits(alphaNumericMode) != 11 { t.Fail() } if v2.charCountBits(byteMode) != 16 { t.Fail() } if v2.charCountBits(kanjiMode) != 10 { t.Fail() } if v3.charCountBits(numericMode) != 14 { t.Fail() } if v3.charCountBits(alphaNumericMode) != 13 { t.Fail() } if v3.charCountBits(byteMode) != 16 { t.Fail() } if v3.charCountBits(kanjiMode) != 12 { t.Fail() } if v1.charCountBits(encodingMode(3)) != 0 { t.Fail() } } func Test_TotalDataBytes(t *testing.T) { if testvi.totalDataBytes() != 20 { t.Fail() } } func Test_ModulWidth(t *testing.T) { if testvi.modulWidth() != 45 { t.Fail() } } func Test_FindSmallestVersionInfo(t *testing.T) { if findSmallestVersionInfo(H, alphaNumericMode, 10208) != nil { t.Error("there should be no version with this capacity") } test := func(cap int, tVersion byte) { v := findSmallestVersionInfo(H, alphaNumericMode, cap) if v == nil || v.Version != tVersion { t.Errorf("version %d should be returned.", tVersion) } } test(10191, 40) test(5591, 29) test(5592, 30) test(190, 3) test(200, 4) } type aligmnentTest struct { version byte patterns []int } var allAligmnentTests = []*aligmnentTest{ &aligmnentTest{1, []int{}}, &aligmnentTest{2, []int{6, 18}}, &aligmnentTest{3, []int{6, 22}}, &aligmnentTest{4, []int{6, 26}}, &aligmnentTest{5, []int{6, 30}}, &aligmnentTest{6, []int{6, 34}}, &aligmnentTest{7, []int{6, 22, 38}}, &aligmnentTest{8, []int{6, 24, 42}}, &aligmnentTest{9, []int{6, 26, 46}}, &aligmnentTest{10, []int{6, 28, 50}}, &aligmnentTest{11, []int{6, 30, 54}}, &aligmnentTest{12, []int{6, 32, 58}}, &aligmnentTest{13, []int{6, 34, 62}}, &aligmnentTest{14, []int{6, 26, 46, 66}}, &aligmnentTest{15, []int{6, 26, 48, 70}}, &aligmnentTest{16, []int{6, 26, 50, 74}}, &aligmnentTest{17, []int{6, 30, 54, 78}}, &aligmnentTest{18, []int{6, 30, 56, 82}}, &aligmnentTest{19, []int{6, 30, 58, 86}}, &aligmnentTest{20, []int{6, 34, 62, 90}}, &aligmnentTest{21, []int{6, 28, 50, 72, 94}}, &aligmnentTest{22, []int{6, 26, 50, 74, 98}}, &aligmnentTest{23, []int{6, 30, 54, 78, 102}}, &aligmnentTest{24, []int{6, 28, 54, 80, 106}}, &aligmnentTest{25, []int{6, 32, 58, 84, 110}}, &aligmnentTest{26, []int{6, 30, 58, 86, 114}}, &aligmnentTest{27, []int{6, 34, 62, 90, 118}}, &aligmnentTest{28, []int{6, 26, 50, 74, 98, 122}}, &aligmnentTest{29, []int{6, 30, 54, 78, 102, 126}}, &aligmnentTest{30, []int{6, 26, 52, 78, 104, 130}}, &aligmnentTest{31, []int{6, 30, 56, 82, 108, 134}}, &aligmnentTest{32, []int{6, 34, 60, 86, 112, 138}}, &aligmnentTest{33, []int{6, 30, 58, 86, 114, 142}}, &aligmnentTest{34, []int{6, 34, 62, 90, 118, 146}}, &aligmnentTest{35, []int{6, 30, 54, 78, 102, 126, 150}}, &aligmnentTest{36, []int{6, 24, 50, 76, 102, 128, 154}}, &aligmnentTest{37, []int{6, 28, 54, 80, 106, 132, 158}}, &aligmnentTest{38, []int{6, 32, 58, 84, 110, 136, 162}}, &aligmnentTest{39, []int{6, 26, 54, 82, 110, 138, 166}}, &aligmnentTest{40, []int{6, 30, 58, 86, 114, 142, 170}}, } func Test_AlignmentPatternPlacements(t *testing.T) { for _, at := range allAligmnentTests { vi := &versionInfo{at.version, M, 0, 0, 0, 0, 0} res := vi.alignmentPatternPlacements() if len(res) != len(at.patterns) { t.Errorf("number of alignmentpatterns missmatch for version %d", at.version) } for i := 0; i < len(res); i++ { if res[i] != at.patterns[i] { t.Errorf("alignmentpatterns for version %d missmatch on index %d", at.version, i) } } } } barcode-1.0.1/scaledbarcode.go000066400000000000000000000054421343272050500162200ustar00rootroot00000000000000package barcode import ( "errors" "fmt" "image" "image/color" "math" ) type wrapFunc func(x, y int) color.Color type scaledBarcode struct { wrapped Barcode wrapperFunc wrapFunc rect image.Rectangle } type intCSscaledBC struct { scaledBarcode } func (bc *scaledBarcode) Content() string { return bc.wrapped.Content() } func (bc *scaledBarcode) Metadata() Metadata { return bc.wrapped.Metadata() } func (bc *scaledBarcode) ColorModel() color.Model { return bc.wrapped.ColorModel() } func (bc *scaledBarcode) Bounds() image.Rectangle { return bc.rect } func (bc *scaledBarcode) At(x, y int) color.Color { return bc.wrapperFunc(x, y) } func (bc *intCSscaledBC) CheckSum() int { if cs, ok := bc.wrapped.(BarcodeIntCS); ok { return cs.CheckSum() } return 0 } // Scale returns a resized barcode with the given width and height. func Scale(bc Barcode, width, height int) (Barcode, error) { switch bc.Metadata().Dimensions { case 1: return scale1DCode(bc, width, height) case 2: return scale2DCode(bc, width, height) } return nil, errors.New("unsupported barcode format") } func newScaledBC(wrapped Barcode, wrapperFunc wrapFunc, rect image.Rectangle) Barcode { result := &scaledBarcode{ wrapped: wrapped, wrapperFunc: wrapperFunc, rect: rect, } if _, ok := wrapped.(BarcodeIntCS); ok { return &intCSscaledBC{*result} } return result } func scale2DCode(bc Barcode, width, height int) (Barcode, error) { orgBounds := bc.Bounds() orgWidth := orgBounds.Max.X - orgBounds.Min.X orgHeight := orgBounds.Max.Y - orgBounds.Min.Y factor := int(math.Min(float64(width)/float64(orgWidth), float64(height)/float64(orgHeight))) if factor <= 0 { return nil, fmt.Errorf("can not scale barcode to an image smaller than %dx%d", orgWidth, orgHeight) } offsetX := (width - (orgWidth * factor)) / 2 offsetY := (height - (orgHeight * factor)) / 2 wrap := func(x, y int) color.Color { if x < offsetX || y < offsetY { return color.White } x = (x - offsetX) / factor y = (y - offsetY) / factor if x >= orgWidth || y >= orgHeight { return color.White } return bc.At(x, y) } return newScaledBC( bc, wrap, image.Rect(0, 0, width, height), ), nil } func scale1DCode(bc Barcode, width, height int) (Barcode, error) { orgBounds := bc.Bounds() orgWidth := orgBounds.Max.X - orgBounds.Min.X factor := int(float64(width) / float64(orgWidth)) if factor <= 0 { return nil, fmt.Errorf("can not scale barcode to an image smaller than %dx1", orgWidth) } offsetX := (width - (orgWidth * factor)) / 2 wrap := func(x, y int) color.Color { if x < offsetX { return color.White } x = (x - offsetX) / factor if x >= orgWidth { return color.White } return bc.At(x, 0) } return newScaledBC( bc, wrap, image.Rect(0, 0, width, height), ), nil } barcode-1.0.1/twooffive/000077500000000000000000000000001343272050500151215ustar00rootroot00000000000000barcode-1.0.1/twooffive/encoder.go000066400000000000000000000063621343272050500170760ustar00rootroot00000000000000// Package twooffive can create interleaved and standard "2 of 5" barcodes. package twooffive import ( "errors" "fmt" "github.com/boombuler/barcode" "github.com/boombuler/barcode/utils" ) const patternWidth = 5 type pattern [patternWidth]bool type encodeInfo struct { start []bool end []bool widths map[bool]int } var ( encodingTable = map[rune]pattern{ '0': pattern{false, false, true, true, false}, '1': pattern{true, false, false, false, true}, '2': pattern{false, true, false, false, true}, '3': pattern{true, true, false, false, false}, '4': pattern{false, false, true, false, true}, '5': pattern{true, false, true, false, false}, '6': pattern{false, true, true, false, false}, '7': pattern{false, false, false, true, true}, '8': pattern{true, false, false, true, false}, '9': pattern{false, true, false, true, false}, } modes = map[bool]encodeInfo{ false: encodeInfo{ // non-interleaved start: []bool{true, true, false, true, true, false, true, false}, end: []bool{true, true, false, true, false, true, true}, widths: map[bool]int{ true: 3, false: 1, }, }, true: encodeInfo{ // interleaved start: []bool{true, false, true, false}, end: []bool{true, true, false, true}, widths: map[bool]int{ true: 3, false: 1, }, }, } nonInterleavedSpace = pattern{false, false, false, false, false} ) // AddCheckSum calculates the correct check-digit and appends it to the given content. func AddCheckSum(content string) (string, error) { if content == "" { return "", errors.New("content is empty") } even := len(content)%2 == 1 sum := 0 for _, r := range content { if _, ok := encodingTable[r]; ok { value := utils.RuneToInt(r) if even { sum += value * 3 } else { sum += value } even = !even } else { return "", fmt.Errorf("can not encode \"%s\"", content) } } return content + string(utils.IntToRune(sum%10)), nil } // Encode creates a codabar barcode for the given content func Encode(content string, interleaved bool) (barcode.Barcode, error) { if content == "" { return nil, errors.New("content is empty") } if interleaved && len(content)%2 == 1 { return nil, errors.New("can only encode even number of digits in interleaved mode") } mode := modes[interleaved] resBits := new(utils.BitList) resBits.AddBit(mode.start...) var lastRune *rune for _, r := range content { var a, b pattern if interleaved { if lastRune == nil { lastRune = new(rune) *lastRune = r continue } else { var o1, o2 bool a, o1 = encodingTable[*lastRune] b, o2 = encodingTable[r] if !o1 || !o2 { return nil, fmt.Errorf("can not encode \"%s\"", content) } lastRune = nil } } else { var ok bool a, ok = encodingTable[r] if !ok { return nil, fmt.Errorf("can not encode \"%s\"", content) } b = nonInterleavedSpace } for i := 0; i < patternWidth; i++ { for x := 0; x < mode.widths[a[i]]; x++ { resBits.AddBit(true) } for x := 0; x < mode.widths[b[i]]; x++ { resBits.AddBit(false) } } } resBits.AddBit(mode.end...) if interleaved { return utils.New1DCode(barcode.Type2of5Interleaved, content, resBits), nil } else { return utils.New1DCode(barcode.Type2of5, content, resBits), nil } } barcode-1.0.1/twooffive/encoder_test.go000066400000000000000000000022661343272050500201340ustar00rootroot00000000000000package twooffive import ( "image/color" "testing" ) func Test_AddCheckSum(t *testing.T) { if sum, err := AddCheckSum("1234567"); err != nil || sum != "12345670" { t.Fail() } if _, err := AddCheckSum("1ABC"); err == nil { t.Fail() } if _, err := AddCheckSum(""); err == nil { t.Fail() } } func Test_Encode(t *testing.T) { _, err := Encode("FOOBAR", false) if err == nil { t.Error("\"FOOBAR\" should not be encodable") } testEncode := func(interleaved bool, txt, testResult string) { code, err := Encode(txt, interleaved) if err != nil || code == nil { t.Fail() } else { if code.Bounds().Max.X != len(testResult) { t.Errorf("%v: length missmatch! %v != %v", txt, code.Bounds().Max.X, len(testResult)) } else { for i, r := range testResult { if (code.At(i, 0) == color.Black) != (r == '1') { t.Errorf("%v: code missmatch on position %d", txt, i) } } } } } testEncode(false, "12345670", "1101101011101010101110101110101011101110111010101010101110101110111010111010101011101110101010101011101110101011101110101101011") testEncode(true, "12345670", "10101110100010101110001110111010001010001110100011100010101010100011100011101101") } barcode-1.0.1/utils/000077500000000000000000000000001343272050500142515ustar00rootroot00000000000000barcode-1.0.1/utils/base1dcode.go000066400000000000000000000024201343272050500165700ustar00rootroot00000000000000// Package utils contain some utilities which are needed to create barcodes package utils import ( "image" "image/color" "github.com/boombuler/barcode" ) type base1DCode struct { *BitList kind string content string } type base1DCodeIntCS struct { base1DCode checksum int } func (c *base1DCode) Content() string { return c.content } func (c *base1DCode) Metadata() barcode.Metadata { return barcode.Metadata{c.kind, 1} } func (c *base1DCode) ColorModel() color.Model { return color.Gray16Model } func (c *base1DCode) Bounds() image.Rectangle { return image.Rect(0, 0, c.Len(), 1) } func (c *base1DCode) At(x, y int) color.Color { if c.GetBit(x) { return color.Black } return color.White } func (c *base1DCodeIntCS) CheckSum() int { return c.checksum } // New1DCodeIntCheckSum creates a new 1D barcode where the bars are represented by the bits in the bars BitList func New1DCodeIntCheckSum(codeKind, content string, bars *BitList, checksum int) barcode.BarcodeIntCS { return &base1DCodeIntCS{base1DCode{bars, codeKind, content}, checksum} } // New1DCode creates a new 1D barcode where the bars are represented by the bits in the bars BitList func New1DCode(codeKind, content string, bars *BitList) barcode.Barcode { return &base1DCode{bars, codeKind, content} } barcode-1.0.1/utils/bitlist.go000066400000000000000000000047701343272050500162620ustar00rootroot00000000000000package utils // BitList is a list that contains bits type BitList struct { count int data []int32 } // NewBitList returns a new BitList with the given length // all bits are initialize with false func NewBitList(capacity int) *BitList { bl := new(BitList) bl.count = capacity x := 0 if capacity%32 != 0 { x = 1 } bl.data = make([]int32, capacity/32+x) return bl } // Len returns the number of contained bits func (bl *BitList) Len() int { return bl.count } func (bl *BitList) grow() { growBy := len(bl.data) if growBy < 128 { growBy = 128 } else if growBy >= 1024 { growBy = 1024 } nd := make([]int32, len(bl.data)+growBy) copy(nd, bl.data) bl.data = nd } // AddBit appends the given bits to the end of the list func (bl *BitList) AddBit(bits ...bool) { for _, bit := range bits { itmIndex := bl.count / 32 for itmIndex >= len(bl.data) { bl.grow() } bl.SetBit(bl.count, bit) bl.count++ } } // SetBit sets the bit at the given index to the given value func (bl *BitList) SetBit(index int, value bool) { itmIndex := index / 32 itmBitShift := 31 - (index % 32) if value { bl.data[itmIndex] = bl.data[itmIndex] | 1<> uint(itmBitShift)) & 1) == 1 } // AddByte appends all 8 bits of the given byte to the end of the list func (bl *BitList) AddByte(b byte) { for i := 7; i >= 0; i-- { bl.AddBit(((b >> uint(i)) & 1) == 1) } } // AddBits appends the last (LSB) 'count' bits of 'b' the the end of the list func (bl *BitList) AddBits(b int, count byte) { for i := int(count) - 1; i >= 0; i-- { bl.AddBit(((b >> uint(i)) & 1) == 1) } } // GetBytes returns all bits of the BitList as a []byte func (bl *BitList) GetBytes() []byte { len := bl.count >> 3 if (bl.count % 8) != 0 { len++ } result := make([]byte, len) for i := 0; i < len; i++ { shift := (3 - (i % 4)) * 8 result[i] = (byte)((bl.data[i/4] >> uint(shift)) & 0xFF) } return result } // IterateBytes iterates through all bytes contained in the BitList func (bl *BitList) IterateBytes() <-chan byte { res := make(chan byte) go func() { c := bl.count shift := 24 i := 0 for c > 0 { res <- byte((bl.data[i] >> uint(shift)) & 0xFF) shift -= 8 if shift < 0 { shift = 24 i++ } c -= 8 } close(res) }() return res } barcode-1.0.1/utils/galoisfield.go000066400000000000000000000024471343272050500170710ustar00rootroot00000000000000package utils // GaloisField encapsulates galois field arithmetics type GaloisField struct { Size int Base int ALogTbl []int LogTbl []int } // NewGaloisField creates a new galois field func NewGaloisField(pp, fieldSize, b int) *GaloisField { result := new(GaloisField) result.Size = fieldSize result.Base = b result.ALogTbl = make([]int, fieldSize) result.LogTbl = make([]int, fieldSize) x := 1 for i := 0; i < fieldSize; i++ { result.ALogTbl[i] = x x = x * 2 if x >= fieldSize { x = (x ^ pp) & (fieldSize - 1) } } for i := 0; i < fieldSize; i++ { result.LogTbl[result.ALogTbl[i]] = int(i) } return result } func (gf *GaloisField) Zero() *GFPoly { return NewGFPoly(gf, []int{0}) } // AddOrSub add or substract two numbers func (gf *GaloisField) AddOrSub(a, b int) int { return a ^ b } // Multiply multiplys two numbers func (gf *GaloisField) Multiply(a, b int) int { if a == 0 || b == 0 { return 0 } return gf.ALogTbl[(gf.LogTbl[a]+gf.LogTbl[b])%(gf.Size-1)] } // Divide divides two numbers func (gf *GaloisField) Divide(a, b int) int { if b == 0 { panic("divide by zero") } else if a == 0 { return 0 } return gf.ALogTbl[(gf.LogTbl[a]-gf.LogTbl[b])%(gf.Size-1)] } func (gf *GaloisField) Invers(num int) int { return gf.ALogTbl[(gf.Size-1)-gf.LogTbl[num]] } barcode-1.0.1/utils/galoisfield_test.go000066400000000000000000000053631343272050500201300ustar00rootroot00000000000000package utils import ( "testing" ) func Test_GF(t *testing.T) { log := []int{ 0, 255, 1, 240, 2, 225, 241, 53, 3, 38, 226, 133, 242, 43, 54, 210, 4, 195, 39, 114, 227, 106, 134, 28, 243, 140, 44, 23, 55, 118, 211, 234, 5, 219, 196, 96, 40, 222, 115, 103, 228, 78, 107, 125, 135, 8, 29, 162, 244, 186, 141, 180, 45, 99, 24, 49, 56, 13, 119, 153, 212, 199, 235, 91, 6, 76, 220, 217, 197, 11, 97, 184, 41, 36, 223, 253, 116, 138, 104, 193, 229, 86, 79, 171, 108, 165, 126, 145, 136, 34, 9, 74, 30, 32, 163, 84, 245, 173, 187, 204, 142, 81, 181, 190, 46, 88, 100, 159, 25, 231, 50, 207, 57, 147, 14, 67, 120, 128, 154, 248, 213, 167, 200, 63, 236, 110, 92, 176, 7, 161, 77, 124, 221, 102, 218, 95, 198, 90, 12, 152, 98, 48, 185, 179, 42, 209, 37, 132, 224, 52, 254, 239, 117, 233, 139, 22, 105, 27, 194, 113, 230, 206, 87, 158, 80, 189, 172, 203, 109, 175, 166, 62, 127, 247, 146, 66, 137, 192, 35, 252, 10, 183, 75, 216, 31, 83, 33, 73, 164, 144, 85, 170, 246, 65, 174, 61, 188, 202, 205, 157, 143, 169, 82, 72, 182, 215, 191, 251, 47, 178, 89, 151, 101, 94, 160, 123, 26, 112, 232, 21, 51, 238, 208, 131, 58, 69, 148, 18, 15, 16, 68, 17, 121, 149, 129, 19, 155, 59, 249, 70, 214, 250, 168, 71, 201, 156, 64, 60, 237, 130, 111, 20, 93, 122, 177, 150, } alog := []int{ 1, 2, 4, 8, 16, 32, 64, 128, 45, 90, 180, 69, 138, 57, 114, 228, 229, 231, 227, 235, 251, 219, 155, 27, 54, 108, 216, 157, 23, 46, 92, 184, 93, 186, 89, 178, 73, 146, 9, 18, 36, 72, 144, 13, 26, 52, 104, 208, 141, 55, 110, 220, 149, 7, 14, 28, 56, 112, 224, 237, 247, 195, 171, 123, 246, 193, 175, 115, 230, 225, 239, 243, 203, 187, 91, 182, 65, 130, 41, 82, 164, 101, 202, 185, 95, 190, 81, 162, 105, 210, 137, 63, 126, 252, 213, 135, 35, 70, 140, 53, 106, 212, 133, 39, 78, 156, 21, 42, 84, 168, 125, 250, 217, 159, 19, 38, 76, 152, 29, 58, 116, 232, 253, 215, 131, 43, 86, 172, 117, 234, 249, 223, 147, 11, 22, 44, 88, 176, 77, 154, 25, 50, 100, 200, 189, 87, 174, 113, 226, 233, 255, 211, 139, 59, 118, 236, 245, 199, 163, 107, 214, 129, 47, 94, 188, 85, 170, 121, 242, 201, 191, 83, 166, 97, 194, 169, 127, 254, 209, 143, 51, 102, 204, 181, 71, 142, 49, 98, 196, 165, 103, 206, 177, 79, 158, 17, 34, 68, 136, 61, 122, 244, 197, 167, 99, 198, 161, 111, 222, 145, 15, 30, 60, 120, 240, 205, 183, 67, 134, 33, 66, 132, 37, 74, 148, 5, 10, 20, 40, 80, 160, 109, 218, 153, 31, 62, 124, 248, 221, 151, 3, 6, 12, 24, 48, 96, 192, 173, 119, 238, 241, 207, 179, 75, 150, 1, } gf := NewGaloisField(301, 256, 1) if len(gf.LogTbl) != len(gf.ALogTbl) || len(gf.LogTbl) != len(log) { t.Fail() } for i := 0; i < len(log); i++ { if gf.LogTbl[i] != log[i] { t.Error("Invalid Log Table") } if gf.ALogTbl[i] != alog[i] { t.Error("Invalid ALog Table") } } } barcode-1.0.1/utils/gfpoly.go000066400000000000000000000054011343272050500161000ustar00rootroot00000000000000package utils type GFPoly struct { gf *GaloisField Coefficients []int } func (gp *GFPoly) Degree() int { return len(gp.Coefficients) - 1 } func (gp *GFPoly) Zero() bool { return gp.Coefficients[0] == 0 } // GetCoefficient returns the coefficient of x ^ degree func (gp *GFPoly) GetCoefficient(degree int) int { return gp.Coefficients[gp.Degree()-degree] } func (gp *GFPoly) AddOrSubstract(other *GFPoly) *GFPoly { if gp.Zero() { return other } else if other.Zero() { return gp } smallCoeff := gp.Coefficients largeCoeff := other.Coefficients if len(smallCoeff) > len(largeCoeff) { largeCoeff, smallCoeff = smallCoeff, largeCoeff } sumDiff := make([]int, len(largeCoeff)) lenDiff := len(largeCoeff) - len(smallCoeff) copy(sumDiff, largeCoeff[:lenDiff]) for i := lenDiff; i < len(largeCoeff); i++ { sumDiff[i] = int(gp.gf.AddOrSub(int(smallCoeff[i-lenDiff]), int(largeCoeff[i]))) } return NewGFPoly(gp.gf, sumDiff) } func (gp *GFPoly) MultByMonominal(degree int, coeff int) *GFPoly { if coeff == 0 { return gp.gf.Zero() } size := len(gp.Coefficients) result := make([]int, size+degree) for i := 0; i < size; i++ { result[i] = int(gp.gf.Multiply(int(gp.Coefficients[i]), int(coeff))) } return NewGFPoly(gp.gf, result) } func (gp *GFPoly) Multiply(other *GFPoly) *GFPoly { if gp.Zero() || other.Zero() { return gp.gf.Zero() } aCoeff := gp.Coefficients aLen := len(aCoeff) bCoeff := other.Coefficients bLen := len(bCoeff) product := make([]int, aLen+bLen-1) for i := 0; i < aLen; i++ { ac := int(aCoeff[i]) for j := 0; j < bLen; j++ { bc := int(bCoeff[j]) product[i+j] = int(gp.gf.AddOrSub(int(product[i+j]), gp.gf.Multiply(ac, bc))) } } return NewGFPoly(gp.gf, product) } func (gp *GFPoly) Divide(other *GFPoly) (quotient *GFPoly, remainder *GFPoly) { quotient = gp.gf.Zero() remainder = gp fld := gp.gf denomLeadTerm := other.GetCoefficient(other.Degree()) inversDenomLeadTerm := fld.Invers(int(denomLeadTerm)) for remainder.Degree() >= other.Degree() && !remainder.Zero() { degreeDiff := remainder.Degree() - other.Degree() scale := int(fld.Multiply(int(remainder.GetCoefficient(remainder.Degree())), inversDenomLeadTerm)) term := other.MultByMonominal(degreeDiff, scale) itQuot := NewMonominalPoly(fld, degreeDiff, scale) quotient = quotient.AddOrSubstract(itQuot) remainder = remainder.AddOrSubstract(term) } return } func NewMonominalPoly(field *GaloisField, degree int, coeff int) *GFPoly { if coeff == 0 { return field.Zero() } result := make([]int, degree+1) result[0] = coeff return NewGFPoly(field, result) } func NewGFPoly(field *GaloisField, coefficients []int) *GFPoly { for len(coefficients) > 1 && coefficients[0] == 0 { coefficients = coefficients[1:] } return &GFPoly{field, coefficients} } barcode-1.0.1/utils/reedsolomon.go000066400000000000000000000021031343272050500171220ustar00rootroot00000000000000package utils import ( "sync" ) type ReedSolomonEncoder struct { gf *GaloisField polynomes []*GFPoly m *sync.Mutex } func NewReedSolomonEncoder(gf *GaloisField) *ReedSolomonEncoder { return &ReedSolomonEncoder{ gf, []*GFPoly{NewGFPoly(gf, []int{1})}, new(sync.Mutex), } } func (rs *ReedSolomonEncoder) getPolynomial(degree int) *GFPoly { rs.m.Lock() defer rs.m.Unlock() if degree >= len(rs.polynomes) { last := rs.polynomes[len(rs.polynomes)-1] for d := len(rs.polynomes); d <= degree; d++ { next := last.Multiply(NewGFPoly(rs.gf, []int{1, rs.gf.ALogTbl[d-1+rs.gf.Base]})) rs.polynomes = append(rs.polynomes, next) last = next } } return rs.polynomes[degree] } func (rs *ReedSolomonEncoder) Encode(data []int, eccCount int) []int { generator := rs.getPolynomial(eccCount) info := NewGFPoly(rs.gf, data) info = info.MultByMonominal(eccCount, 1) _, remainder := info.Divide(generator) result := make([]int, eccCount) numZero := int(eccCount) - len(remainder.Coefficients) copy(result[numZero:], remainder.Coefficients) return result } barcode-1.0.1/utils/runeint.go000066400000000000000000000007121343272050500162640ustar00rootroot00000000000000package utils // RuneToInt converts a rune between '0' and '9' to an integer between 0 and 9 // If the rune is outside of this range -1 is returned. func RuneToInt(r rune) int { if r >= '0' && r <= '9' { return int(r - '0') } return -1 } // IntToRune converts a digit 0 - 9 to the rune '0' - '9'. If the given int is outside // of this range 'F' is returned! func IntToRune(i int) rune { if i >= 0 && i <= 9 { return rune(i + '0') } return 'F' } barcode-1.0.1/utils/runeint_test.go000066400000000000000000000011621343272050500173230ustar00rootroot00000000000000package utils import "testing" func Test_RuneToIntIntToRune(t *testing.T) { if IntToRune(0) != '0' { t.Errorf("failed IntToRune(0) returned %d", IntToRune(0)) } if IntToRune(9) != '9' { t.Errorf("failed IntToRune(9) returned %d", IntToRune(9)) } if IntToRune(10) != 'F' { t.Errorf("failed IntToRune(10) returned %d", IntToRune(10)) } if RuneToInt('0') != 0 { t.Errorf("failed RuneToInt('0') returned %d", RuneToInt(0)) } if RuneToInt('9') != 9 { t.Errorf("failed RuneToInt('9') returned %d", RuneToInt(9)) } if RuneToInt('F') != -1 { t.Errorf("failed RuneToInt('F') returned %d", RuneToInt('F')) } }