diff --git a/codabar/codabarcode.go b/codabar/codabarcode.go deleted file mode 100644 index c7ef230..0000000 --- a/codabar/codabarcode.go +++ /dev/null @@ -1,36 +0,0 @@ -package codabar - -import ( - "github.com/boombuler/barcode" - "github.com/boombuler/barcode/utils" - "image" - "image/color" -) - -type codabarcode struct { - *utils.BitList - content string -} - -func (c *codabarcode) Content() string { - return c.content -} - -func (c *codabarcode) Metadata() barcode.Metadata { - return barcode.Metadata{"Codabar", 1} -} - -func (c *codabarcode) ColorModel() color.Model { - return color.Gray16Model -} - -func (c *codabarcode) Bounds() image.Rectangle { - return image.Rect(0, 0, c.Len(), 1) -} - -func (c *codabarcode) At(x, y int) color.Color { - if c.GetBit(x) { - return color.Black - } - return color.White -} diff --git a/codabar/encoder.go b/codabar/encoder.go index 4a4be1d..31243fe 100644 --- a/codabar/encoder.go +++ b/codabar/encoder.go @@ -44,9 +44,7 @@ func Encode(content string) (barcode.Barcode, error) { if !ok { return nil, fmt.Errorf("can not encode \"%s\"", content) } - for _, bit := range bits { - resBits.AddBit(bit) - } + resBits.AddBit(bits...) } - return &codabarcode{resBits, content}, nil + return utils.New1DCode("Codabar", content, resBits), nil } diff --git a/code128/bencoder.go b/code128/bencoder.go deleted file mode 100644 index cee8874..0000000 --- a/code128/bencoder.go +++ /dev/null @@ -1,21 +0,0 @@ -package code128 - -import ( - "github.com/boombuler/barcode/utils" - "strings" -) - -const bTable = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" - -func encodeBTable(content []rune) *utils.BitList { - result := new(utils.BitList) - result.AddByte(startBSymbol) - for _, r := range content { - idx := strings.IndexRune(bTable, r) - if idx < 0 { - return nil - } - result.AddByte(byte(idx)) - } - return result -} diff --git a/code128/code.go b/code128/code.go deleted file mode 100644 index e2dbb8c..0000000 --- a/code128/code.go +++ /dev/null @@ -1,36 +0,0 @@ -package code128 - -import ( - "github.com/boombuler/barcode" - "github.com/boombuler/barcode/utils" - "image" - "image/color" -) - -type code struct { - *utils.BitList - content string -} - -func (c *code) Content() string { - return c.content -} - -func (c *code) Metadata() barcode.Metadata { - return barcode.Metadata{"Code 128", 1} -} - -func (c *code) ColorModel() color.Model { - return color.Gray16Model -} - -func (c *code) Bounds() image.Rectangle { - return image.Rect(0, 0, c.Len(), 1) -} - -func (c *code) At(x, y int) color.Color { - if c.GetBit(x) { - return color.Black - } - return color.White -} diff --git a/code128/encode.go b/code128/encode.go index 0e70375..50386cf 100644 --- a/code128/encode.go +++ b/code128/encode.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/boombuler/barcode" "github.com/boombuler/barcode/utils" + "strings" "unicode/utf8" ) @@ -17,15 +18,65 @@ func strToRunes(str string) []rune { 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 nextRunes[i] < '0' || nextRunes[i] > '9' { + return false + } + } + return true +} + +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 +} + func Encode(content string) (barcode.Barcode, error) { contentRunes := strToRunes(content) - idxList := encodeBTable(contentRunes) + 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 := &code{new(utils.BitList), content} + result := new(utils.BitList) sum := 0 for i, idx := range idxList.GetBytes() { if i == 0 { @@ -33,9 +84,9 @@ func Encode(content string) (barcode.Barcode, error) { } else { sum += i * int(idx) } - result.AddRange(encodingTable[idx]) + result.AddBit(encodingTable[idx]...) } - result.AddRange(encodingTable[sum%103]) - result.AddRange(encodingTable[stopSymbol]) - return result, nil + result.AddBit(encodingTable[sum%103]...) + result.AddBit(encodingTable[stopSymbol]...) + return utils.New1DCode("Code 128", content, result), nil } diff --git a/code128/encodingtable.go b/code128/encodingtable.go index a94ad6f..a102821 100644 --- a/code128/encodingtable.go +++ b/code128/encodingtable.go @@ -114,3 +114,5 @@ const startASymbol byte = 103 const startBSymbol byte = 104 const startCSymbol byte = 105 const stopSymbol byte = 106 + +const bTable = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" diff --git a/code39/code.go b/code39/code.go deleted file mode 100644 index 5298e4c..0000000 --- a/code39/code.go +++ /dev/null @@ -1,40 +0,0 @@ -package code39 - -import ( - "github.com/boombuler/barcode" - "github.com/boombuler/barcode/utils" - "image" - "image/color" -) - -type code struct { - *utils.BitList - content string -} - -func newCode() *code { - return &code{new(utils.BitList), ""} -} - -func (c *code) Content() string { - return c.content -} - -func (c *code) Metadata() barcode.Metadata { - return barcode.Metadata{"Code39", 1} -} - -func (c *code) ColorModel() color.Model { - return color.Gray16Model -} - -func (c *code) Bounds() image.Rectangle { - return image.Rect(0, 0, c.Len(), 1) -} - -func (c *code) At(x, y int) color.Color { - if c.GetBit(x) { - return color.Black - } - return color.White -} diff --git a/code39/encoder.go b/code39/encoder.go index 8387b34..290bb58 100644 --- a/code39/encoder.go +++ b/code39/encoder.go @@ -3,6 +3,7 @@ package code39 import ( "errors" "github.com/boombuler/barcode" + "github.com/boombuler/barcode/utils" "strings" ) @@ -91,22 +92,19 @@ func Encode(content string, includeChecksum bool) (barcode.Barcode, error) { } data += "*" - cd := newCode() - cd.content = content + result := new(utils.BitList) for i, r := range data { if i != 0 { - cd.AddBit(false) + result.AddBit(false) } info, ok := encodeTable[r] if !ok { return nil, errors.New("invalid data") } - for _, bit := range info.data { - cd.AddBit(bit) - } + result.AddBit(info.data...) } - return cd, nil + return utils.New1DCode("Code 39", content, result), nil } diff --git a/ean/eancode.go b/ean/eancode.go deleted file mode 100644 index 44f55cb..0000000 --- a/ean/eancode.go +++ /dev/null @@ -1,47 +0,0 @@ -package ean - -import ( - "github.com/boombuler/barcode" - "github.com/boombuler/barcode/utils" - "image" - "image/color" -) - -type eancode struct { - *utils.BitList - content string -} - -func newEANCode(isEAN8 bool) *eancode { - capacity := 95 - if isEAN8 { - capacity = 67 - } - return &eancode{utils.NewBitList(capacity), ""} -} - -func (c *eancode) Content() string { - return c.content -} - -func (c *eancode) Metadata() barcode.Metadata { - if c.Len() == 67 { - return barcode.Metadata{"EAN 8", 1} - } - return barcode.Metadata{"EAN 13", 1} -} - -func (c *eancode) ColorModel() color.Model { - return color.Gray16Model -} - -func (c *eancode) Bounds() image.Rectangle { - return image.Rect(0, 0, c.Len(), 1) -} - -func (c *eancode) At(x, y int) color.Color { - if c.GetBit(x) { - return color.Black - } - return color.White -} diff --git a/ean/encoder.go b/ean/encoder.go index f7e674b..fd2852a 100644 --- a/ean/encoder.go +++ b/ean/encoder.go @@ -4,6 +4,7 @@ package ean import ( "errors" "github.com/boombuler/barcode" + "github.com/boombuler/barcode/utils" ) type encodedNumber struct { @@ -146,21 +147,14 @@ func calcCheckNum(code string) rune { return intToRune((10 - (sum % 10)) % 10) } -func encodeEAN8(code string, result *eancode) bool { - pos := 0 - appendBit := func(b bool) { - result.SetBit(pos, b) - pos++ - } - - appendBit(true) - appendBit(false) - appendBit(true) +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 false + return nil } var data []bool if cpos < 4 { @@ -170,39 +164,24 @@ func encodeEAN8(code string, result *eancode) bool { } if cpos == 4 { - appendBit(false) - appendBit(true) - appendBit(false) - appendBit(true) - appendBit(false) - } - for _, bit := range data { - appendBit(bit) + result.AddBit(false, true, false, true, false) } + result.AddBit(data...) } + result.AddBit(true, false, true) - appendBit(true) - appendBit(false) - appendBit(true) - return true + return result } -func encodeEAN13(code string, result *eancode) bool { - pos := 0 - appendBit := func(b bool) { - result.SetBit(pos, b) - pos++ - } - - appendBit(true) - appendBit(false) - appendBit(true) +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 false + return nil } if cpos == 0 { firstNum = num.CheckSum @@ -221,21 +200,12 @@ func encodeEAN13(code string, result *eancode) bool { } if cpos == 7 { - appendBit(false) - appendBit(true) - appendBit(false) - appendBit(true) - appendBit(false) - } - - for _, bit := range data { - appendBit(bit) + result.AddBit(false, true, false, true, false) } + result.AddBit(data...) } - appendBit(true) - appendBit(false) - appendBit(true) - return true + result.AddByte(true, false, true) + return result } // encodes the given EAN 8 or EAN 13 number to a barcode image @@ -249,18 +219,17 @@ func Encode(code string) (barcode.Barcode, error) { return nil, errors.New("checksum missmatch!") } } - ean8 := false + var result *utils.BitList = nil if len(code) == 8 { - ean8 = true - - } else if len(code) != 13 { - return nil, errors.New("invalid ean code data") + result := encodeEAN8(code) + if result != nil { + return utils.New1DCode("EAN 8", code, result), nil + } + } else if len(code) == 13 { + result := encodeEAN13(code) + if result != nil { + return utils.New1DCode("EAN 13", code, result), nil + } } - result := newEANCode(ean8) - if (ean8 && encodeEAN8(code, result)) || (!ean8 && encodeEAN13(code, result)) { - result.content = code - return result, nil - } - - return nil, errors.New("ean code contains invalid characters") + return nil, errors.New("invalid ean code data") } diff --git a/utils/base1dcode.go b/utils/base1dcode.go new file mode 100644 index 0000000..bf4c606 --- /dev/null +++ b/utils/base1dcode.go @@ -0,0 +1,40 @@ +package utils + +import ( + "github.com/boombuler/barcode" + "image" + "image/color" +) + +type base1DCode struct { + *BitList + kind string + content string +} + +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 New1DCode(codeKind, content string, bars *BitList) barcode.Barcode { + return &base1DCode{bars, codeKind, content} +} diff --git a/utils/bitlist.go b/utils/bitlist.go index 2780720..04de950 100644 --- a/utils/bitlist.go +++ b/utils/bitlist.go @@ -37,14 +37,16 @@ func (bl *BitList) grow() { bl.data = nd } -// appends the given bit to the end of the list -func (bl *BitList) AddBit(bit bool) { - itmIndex := bl.count / 32 - for itmIndex >= len(bl.data) { - bl.grow() +// 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++ } - bl.SetBit(bl.count, bit) - bl.count++ } // sets the bit at the given index to the given value @@ -79,13 +81,6 @@ func (bl *BitList) AddBits(b int, count byte) { } } -// appends all bits in the bool-slice to the end of the list -func (bl *BitList) AddRange(bits []bool) { - for _, b := range bits { - bl.AddBit(b) - } -} - // returns all bits of the BitList as a []byte func (bl *BitList) GetBytes() []byte { len := bl.count >> 3