예제 #1
0
// 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.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! 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...)
	}

	return utils.New1DCode("Code 39", content, result), nil
}
예제 #2
0
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
}
예제 #3
0
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
}
예제 #4
0
// 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...)

	kindTxt := ""
	if interleaved {
		kindTxt = " (interleaved)"
	}
	return utils.New1DCode("2 of 5"+kindTxt, content, resBits, -1), nil
}
예제 #5
0
// 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("Codabar", content, resBits), nil
}
예제 #6
0
func Encode(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)
	sum := 0
	for i, idx := range idxList.GetBytes() {
		if i == 0 {
			sum = int(idx)
		} else {
			sum += i * int(idx)
		}
		result.AddBit(encodingTable[idx]...)
	}
	result.AddBit(encodingTable[sum%103]...)
	result.AddBit(encodingTable[stopSymbol]...)
	return utils.New1DCode("Code 128", content, result), nil
}
예제 #7
0
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
}
예제 #8
0
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
}
예제 #9
0
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
}
예제 #10
0
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 {
				result.AddByte(startCSymbol)
				curEncoding = startCSymbol
			}
			idx := (content[i] - '0') * 10
			i++
			idx = idx + (content[i] - '0')

			result.AddByte(byte(idx))
		} else {
			if curEncoding != startBSymbol {
				result.AddByte(startBSymbol)
				curEncoding = startBSymbol
			}
			idx := strings.IndexRune(bTable, content[i])
			if idx < 0 {
				return nil
			}
			result.AddByte(byte(idx))
		}
	}
	fmt.Println(result.GetBytes())
	return result
}
예제 #11
0
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
			}
			idx := (content[i] - '0') * 10
			i++
			idx = idx + (content[i] - '0')

			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
}
예제 #12
0
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)
		}
	}
}