updated docs and code cleanup

This commit is contained in:
Florian Sundermann 2014-08-11 11:11:24 +02:00
parent bccb3d2ede
commit d0cdae0475
10 changed files with 137 additions and 106 deletions

16
README.md Normal file
View File

@ -0,0 +1,16 @@
##Introduction##
This is a package for GO which can be used to create different types of barcodes.
##Supported Barcode Types##
* Codabar
* Code 128
* Code 39
* EAN 8
* EAN 13
* Datamatrix
* QR Codes
##Documentation##
See [GoDoc](https://godoc.org/github.com/boombuler/barcode)
To create a barcode use the Encode function from one of the subpackages.

View File

@ -1,13 +1,15 @@
// Package codabar can create Codabar barcodes
package codabar package codabar
import ( import (
"fmt" "fmt"
"regexp"
"github.com/boombuler/barcode" "github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils" "github.com/boombuler/barcode/utils"
"regexp"
) )
var encodingTable map[rune][]bool = map[rune][]bool{ var encodingTable = map[rune][]bool{
'0': []bool{true, false, true, false, true, false, false, true, true}, '0': []bool{true, false, true, false, true, false, false, true, true},
'1': []bool{true, false, true, false, true, true, false, false, true}, '1': []bool{true, false, true, false, true, true, false, false, true},
'2': []bool{true, false, true, false, false, true, false, true, true}, '2': []bool{true, false, true, false, false, true, false, true, true},
@ -30,6 +32,7 @@ var encodingTable map[rune][]bool = map[rune][]bool{
'D': []bool{true, false, true, false, false, true, true, false, false, 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) { func Encode(content string) (barcode.Barcode, error) {
checkValid, _ := regexp.Compile(`[ABCD][0123456789\-\$\:/\.\+]*[ABCD]$`) checkValid, _ := regexp.Compile(`[ABCD][0123456789\-\$\:/\.\+]*[ABCD]$`)
if content == "!" || checkValid.ReplaceAllString(content, "!") != "!" { if content == "!" || checkValid.ReplaceAllString(content, "!") != "!" {
@ -40,11 +43,7 @@ func Encode(content string) (barcode.Barcode, error) {
if i > 0 { if i > 0 {
resBits.AddBit(false) resBits.AddBit(false)
} }
bits, ok := encodingTable[r] resBits.AddBit(encodingTable[r]...)
if !ok {
return nil, fmt.Errorf("can not encode \"%s\"", content)
}
resBits.AddBit(bits...)
} }
return utils.New1DCode("Codabar", content, resBits), nil return utils.New1DCode("Codabar", content, resBits), nil
} }

View File

@ -1,11 +1,13 @@
// Package code128 can create Code128 barcodes
package code128 package code128
import ( import (
"fmt" "fmt"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
"strings" "strings"
"unicode/utf8" "unicode/utf8"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
) )
func strToRunes(str string) []rune { func strToRunes(str string) []rune {
@ -65,6 +67,7 @@ func getCodeIndexList(content []rune) *utils.BitList {
return result return result
} }
// Encode creates a Code 128 barcode for the given content
func Encode(content string) (barcode.Barcode, error) { func Encode(content string) (barcode.Barcode, error) {
contentRunes := strToRunes(content) contentRunes := strToRunes(content)
if len(contentRunes) < 0 || len(contentRunes) > 80 { if len(contentRunes) < 0 || len(contentRunes) > 80 {

View File

@ -1,10 +1,12 @@
// Package code39 can create Code39 barcodes
package code39 package code39
import ( import (
"errors" "errors"
"strings"
"github.com/boombuler/barcode" "github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils" "github.com/boombuler/barcode/utils"
"strings"
) )
type encodeInfo struct { type encodeInfo struct {
@ -12,7 +14,7 @@ type encodeInfo struct {
data []bool data []bool
} }
var encodeTable map[rune]encodeInfo = map[rune]encodeInfo{ var encodeTable = map[rune]encodeInfo{
'0': encodeInfo{0, []bool{true, false, true, false, false, true, true, false, true, true, false, true}}, '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}}, '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}}, '2': encodeInfo{2, []bool{true, false, true, true, false, false, true, false, true, false, true, true}},
@ -59,7 +61,7 @@ var encodeTable map[rune]encodeInfo = map[rune]encodeInfo{
'*': encodeInfo{-1, []bool{true, false, false, true, false, true, true, false, true, true, false, true}}, '*': encodeInfo{-1, []bool{true, false, false, true, false, true, true, false, true, true, false, true}},
} }
var extendedTable map[rune]string = map[rune]string{ 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`, 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`, 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`, 21: `$U`, 22: `$V`, 23: `$W`, 24: `$X`, 25: `$Y`, 26: `$Z`, 27: `%A`, 28: `%B`, 29: `%C`, 30: `%D`,
@ -108,7 +110,7 @@ func prepare(content string) (string, error) {
return result, nil return result, nil
} }
// encodes the given string as a code39 barcode // 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 // 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) { func Encode(content string, includeChecksum bool, fullASCIIMode bool) (barcode.Barcode, error) {
if fullASCIIMode { if fullASCIIMode {

View File

@ -1,75 +1,77 @@
package datamatrix // Package datamatrix can create Datamatrix barcodes
package datamatrix
import (
"errors" import (
"github.com/boombuler/barcode" "errors"
)
"github.com/boombuler/barcode"
// Encodes the given content as a DataMatrix code )
func Encode(content string) (barcode.Barcode, error) {
data := encodeText(content) // Encode returns a Datamatrix barcode for the given content
func Encode(content string) (barcode.Barcode, error) {
var size *dmCodeSize = nil data := encodeText(content)
for _, s := range codeSizes {
if s.DataCodewords() >= len(data) { var size *dmCodeSize
size = s for _, s := range codeSizes {
break if s.DataCodewords() >= len(data) {
} size = s
} break
if size == nil { }
return nil, errors.New("to much data to encode") }
} if size == nil {
data = addPadding(data, size.DataCodewords()) return nil, errors.New("to much data to encode")
data = ec.calcECC(data, size) }
code := render(data, size) data = addPadding(data, size.DataCodewords())
if code != nil { data = ec.calcECC(data, size)
code.content = content code := render(data, size)
return code, nil if code != nil {
} code.content = content
return nil, errors.New("unable to render barcode") return code, nil
} }
return nil, errors.New("unable to render barcode")
func render(data []byte, size *dmCodeSize) *datamatrixCode { }
cl := newCodeLayout(size)
func render(data []byte, size *dmCodeSize) *datamatrixCode {
setters := cl.IterateSetter() cl := newCodeLayout(size)
for _, b := range data {
(<-setters)(b) setters := cl.IterateSetter()
} for _, b := range data {
return cl.Merge() (<-setters)(b)
} }
return cl.Merge()
func encodeText(content string) []byte { }
result := make([]byte, 0)
input := []byte(content) func encodeText(content string) []byte {
var result []byte
for i := 0; i < len(input); { input := []byte(content)
c := input[i]
i++ for i := 0; i < len(input); {
c := input[i]
if c >= '0' && c <= '9' && i < len(input) && input[i] >= '0' && input[i] <= '9' { i++
// two numbers...
c2 := input[i] if c >= '0' && c <= '9' && i < len(input) && input[i] >= '0' && input[i] <= '9' {
i++ // two numbers...
cw := byte(((c-'0')*10 + (c2 - '0')) + 130) c2 := input[i]
result = append(result, cw) i++
} else if c > 127 { cw := byte(((c-'0')*10 + (c2 - '0')) + 130)
// not correct... needs to be redone later... result = append(result, cw)
result = append(result, 235, c-127) } else if c > 127 {
} else { // not correct... needs to be redone later...
result = append(result, c+1) result = append(result, 235, c-127)
} } else {
} result = append(result, c+1)
return result }
} }
return result
func addPadding(data []byte, toCount int) []byte { }
if len(data) < toCount {
data = append(data, 129) func addPadding(data []byte, toCount int) []byte {
} if len(data) < toCount {
for len(data) < toCount { data = append(data, 129)
R := ((149 * (len(data) + 1)) % 253) + 1 }
data = append(data, byte((129+R)%254)) for len(data) < toCount {
} R := ((149 * (len(data) + 1)) % 253) + 1
return data data = append(data, byte((129+R)%254))
} }
return data
}

View File

@ -1,8 +1,9 @@
// package for EAN barcode generation. // Package ean can create EAN 8 and EAN 13 barcodes.
package ean package ean
import ( import (
"errors" "errors"
"github.com/boombuler/barcode" "github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils" "github.com/boombuler/barcode/utils"
) )
@ -14,7 +15,7 @@ type encodedNumber struct {
CheckSum []bool CheckSum []bool
} }
var encoderTable map[rune]encodedNumber = map[rune]encodedNumber{ var encoderTable = map[rune]encodedNumber{
'0': encodedNumber{ '0': encodedNumber{
[]bool{false, false, false, true, true, false, true}, []bool{false, false, false, true, true, false, true},
[]bool{false, true, false, false, true, true, true}, []bool{false, true, false, false, true, true, true},
@ -170,7 +171,7 @@ func encodeEAN13(code string) *utils.BitList {
return result return result
} }
// encodes the given EAN 8 or EAN 13 number to a barcode image // Encode returns a EAN 8 or EAN 13 barcode for the given code
func Encode(code string) (barcode.Barcode, error) { func Encode(code string) (barcode.Barcode, error) {
if len(code) == 7 || len(code) == 12 { if len(code) == 7 || len(code) == 12 {
code += string(calcCheckNum(code)) code += string(calcCheckNum(code))
@ -178,7 +179,7 @@ func Encode(code string) (barcode.Barcode, error) {
check := code[0 : len(code)-1] check := code[0 : len(code)-1]
check += string(calcCheckNum(check)) check += string(calcCheckNum(check))
if check != code { if check != code {
return nil, errors.New("checksum missmatch!") return nil, errors.New("checksum missmatch")
} }
} }

View File

@ -36,7 +36,7 @@ func (bc *scaledBarcode) At(x, y int) color.Color {
return bc.wrapperFunc(x, y) return bc.wrapperFunc(x, y)
} }
// returns a resized barcode with the given width and height. // Scale returns a resized barcode with the given width and height.
func Scale(bc Barcode, width, height int) (Barcode, error) { func Scale(bc Barcode, width, height int) (Barcode, error) {
switch bc.Metadata().Dimensions { switch bc.Metadata().Dimensions {
case 1: case 1:

View File

@ -1,9 +1,11 @@
// Package utils contain some utilities which are needed to create barcodes
package utils package utils
import ( import (
"github.com/boombuler/barcode"
"image" "image"
"image/color" "image/color"
"github.com/boombuler/barcode"
) )
type base1DCode struct { type base1DCode struct {
@ -35,6 +37,7 @@ func (c *base1DCode) At(x, y int) color.Color {
return color.White return color.White
} }
// 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 { func New1DCode(codeKind, content string, bars *BitList) barcode.Barcode {
return &base1DCode{bars, codeKind, content} return &base1DCode{bars, codeKind, content}
} }

View File

@ -1,12 +1,12 @@
package utils package utils
// utility class that contains bits // BitList is a list that contains bits
type BitList struct { type BitList struct {
count int count int
data []int32 data []int32
} }
// returns a new BitList with the given length // NewBitList returns a new BitList with the given length
// all bits are initialize with false // all bits are initialize with false
func NewBitList(capacity int) *BitList { func NewBitList(capacity int) *BitList {
bl := new(BitList) bl := new(BitList)
@ -19,7 +19,7 @@ func NewBitList(capacity int) *BitList {
return bl return bl
} }
// returns the number of contained bits // Len returns the number of contained bits
func (bl *BitList) Len() int { func (bl *BitList) Len() int {
return bl.count return bl.count
} }
@ -37,7 +37,7 @@ func (bl *BitList) grow() {
bl.data = nd bl.data = nd
} }
// appends the given bits to the end of the list // AddBit appends the given bits to the end of the list
func (bl *BitList) AddBit(bits ...bool) { func (bl *BitList) AddBit(bits ...bool) {
for _, bit := range bits { for _, bit := range bits {
itmIndex := bl.count / 32 itmIndex := bl.count / 32
@ -49,7 +49,7 @@ func (bl *BitList) AddBit(bits ...bool) {
} }
} }
// sets the bit at the given index to the given value // SetBit sets the bit at the given index to the given value
func (bl *BitList) SetBit(index int, value bool) { func (bl *BitList) SetBit(index int, value bool) {
itmIndex := index / 32 itmIndex := index / 32
itmBitShift := 31 - (index % 32) itmBitShift := 31 - (index % 32)
@ -60,32 +60,32 @@ func (bl *BitList) SetBit(index int, value bool) {
} }
} }
// returns the bit at the given index // GetBit returns the bit at the given index
func (bl *BitList) GetBit(index int) bool { func (bl *BitList) GetBit(index int) bool {
itmIndex := index / 32 itmIndex := index / 32
itmBitShift := 31 - (index % 32) itmBitShift := 31 - (index % 32)
return ((bl.data[itmIndex] >> uint(itmBitShift)) & 1) == 1 return ((bl.data[itmIndex] >> uint(itmBitShift)) & 1) == 1
} }
// appends all 8 bits of the given byte to the end of the list // AddByte appends all 8 bits of the given byte to the end of the list
func (bl *BitList) AddByte(b byte) { func (bl *BitList) AddByte(b byte) {
for i := 7; i >= 0; i-- { for i := 7; i >= 0; i-- {
bl.AddBit(((b >> uint(i)) & 1) == 1) bl.AddBit(((b >> uint(i)) & 1) == 1)
} }
} }
// appends the last (LSB) 'count' bits of 'b' the the end of the list // AddBits appends the last (LSB) 'count' bits of 'b' the the end of the list
func (bl *BitList) AddBits(b int, count byte) { func (bl *BitList) AddBits(b int, count byte) {
for i := int(count - 1); i >= 0; i-- { for i := int(count - 1); i >= 0; i-- {
bl.AddBit(((b >> uint(i)) & 1) == 1) bl.AddBit(((b >> uint(i)) & 1) == 1)
} }
} }
// returns all bits of the BitList as a []byte // GetBytes returns all bits of the BitList as a []byte
func (bl *BitList) GetBytes() []byte { func (bl *BitList) GetBytes() []byte {
len := bl.count >> 3 len := bl.count >> 3
if (bl.count % 8) != 0 { if (bl.count % 8) != 0 {
len += 1 len++
} }
result := make([]byte, len) result := make([]byte, len)
for i := 0; i < len; i++ { for i := 0; i < len; i++ {
@ -95,7 +95,7 @@ func (bl *BitList) GetBytes() []byte {
return result return result
} }
// iterates through all bytes contained in the BitList // IterateBytes iterates through all bytes contained in the BitList
func (bl *BitList) IterateBytes() <-chan byte { func (bl *BitList) IterateBytes() <-chan byte {
res := make(chan byte) res := make(chan byte)
@ -108,7 +108,7 @@ func (bl *BitList) IterateBytes() <-chan byte {
shift -= 8 shift -= 8
if shift < 0 { if shift < 0 {
shift = 24 shift = 24
i += 1 i++
} }
c -= 8 c -= 8
} }

View File

@ -1,10 +1,12 @@
package utils package utils
// GaloisField encapsulates galois field arithmetics
type GaloisField struct { type GaloisField struct {
ALogTbl []int ALogTbl []int
LogTbl []int LogTbl []int
} }
// NewGaloisField creates a new falois field
func NewGaloisField(pp int) *GaloisField { func NewGaloisField(pp int) *GaloisField {
result := new(GaloisField) result := new(GaloisField)
fldSize := 256 fldSize := 256
@ -28,10 +30,12 @@ func NewGaloisField(pp int) *GaloisField {
return result return result
} }
// AddOrSub add or substract two numbers
func (gf *GaloisField) AddOrSub(a, b int) int { func (gf *GaloisField) AddOrSub(a, b int) int {
return a ^ b return a ^ b
} }
// Multiply multiplys two numbers
func (gf *GaloisField) Multiply(a, b int) int { func (gf *GaloisField) Multiply(a, b int) int {
if a == 0 || b == 0 { if a == 0 || b == 0 {
return 0 return 0
@ -39,6 +43,7 @@ func (gf *GaloisField) Multiply(a, b int) int {
return gf.ALogTbl[(gf.LogTbl[a]+gf.LogTbl[b])%255] return gf.ALogTbl[(gf.LogTbl[a]+gf.LogTbl[b])%255]
} }
// Divide divides two numbers
func (gf *GaloisField) Divide(a, b int) int { func (gf *GaloisField) Divide(a, b int) int {
if b == 0 { if b == 0 {
panic("divide by zero") panic("divide by zero")