1
2 package ean
3
4 import (
5 "errors"
6
7 "github.com/boombuler/barcode"
8 "github.com/boombuler/barcode/utils"
9 )
10
11 type encodedNumber struct {
12 LeftOdd []bool
13 LeftEven []bool
14 Right []bool
15 CheckSum []bool
16 }
17
18 var encoderTable = map[rune]encodedNumber{
19 '0': encodedNumber{
20 []bool{false, false, false, true, true, false, true},
21 []bool{false, true, false, false, true, true, true},
22 []bool{true, true, true, false, false, true, false},
23 []bool{false, false, false, false, false, false},
24 },
25 '1': encodedNumber{
26 []bool{false, false, true, true, false, false, true},
27 []bool{false, true, true, false, false, true, true},
28 []bool{true, true, false, false, true, true, false},
29 []bool{false, false, true, false, true, true},
30 },
31 '2': encodedNumber{
32 []bool{false, false, true, false, false, true, true},
33 []bool{false, false, true, true, false, true, true},
34 []bool{true, true, false, true, true, false, false},
35 []bool{false, false, true, true, false, true},
36 },
37 '3': encodedNumber{
38 []bool{false, true, true, true, true, false, true},
39 []bool{false, true, false, false, false, false, true},
40 []bool{true, false, false, false, false, true, false},
41 []bool{false, false, true, true, true, false},
42 },
43 '4': encodedNumber{
44 []bool{false, true, false, false, false, true, true},
45 []bool{false, false, true, true, true, false, true},
46 []bool{true, false, true, true, true, false, false},
47 []bool{false, true, false, false, true, true},
48 },
49 '5': encodedNumber{
50 []bool{false, true, true, false, false, false, true},
51 []bool{false, true, true, true, false, false, true},
52 []bool{true, false, false, true, true, true, false},
53 []bool{false, true, true, false, false, true},
54 },
55 '6': encodedNumber{
56 []bool{false, true, false, true, true, true, true},
57 []bool{false, false, false, false, true, false, true},
58 []bool{true, false, true, false, false, false, false},
59 []bool{false, true, true, true, false, false},
60 },
61 '7': encodedNumber{
62 []bool{false, true, true, true, false, true, true},
63 []bool{false, false, true, false, false, false, true},
64 []bool{true, false, false, false, true, false, false},
65 []bool{false, true, false, true, false, true},
66 },
67 '8': encodedNumber{
68 []bool{false, true, true, false, true, true, true},
69 []bool{false, false, false, true, false, false, true},
70 []bool{true, false, false, true, false, false, false},
71 []bool{false, true, false, true, true, false},
72 },
73 '9': encodedNumber{
74 []bool{false, false, false, true, false, true, true},
75 []bool{false, false, true, false, true, true, true},
76 []bool{true, true, true, false, true, false, false},
77 []bool{false, true, true, false, true, false},
78 },
79 }
80
81 func calcCheckNum(code string) rune {
82 x3 := len(code) == 7
83 sum := 0
84 for _, r := range code {
85 curNum := utils.RuneToInt(r)
86 if curNum < 0 || curNum > 9 {
87 return 'B'
88 }
89 if x3 {
90 curNum = curNum * 3
91 }
92 x3 = !x3
93 sum += curNum
94 }
95
96 return utils.IntToRune((10 - (sum % 10)) % 10)
97 }
98
99 func encodeEAN8(code string) *utils.BitList {
100 result := new(utils.BitList)
101 result.AddBit(true, false, true)
102
103 for cpos, r := range code {
104 num, ok := encoderTable[r]
105 if !ok {
106 return nil
107 }
108 var data []bool
109 if cpos < 4 {
110 data = num.LeftOdd
111 } else {
112 data = num.Right
113 }
114
115 if cpos == 4 {
116 result.AddBit(false, true, false, true, false)
117 }
118 result.AddBit(data...)
119 }
120 result.AddBit(true, false, true)
121
122 return result
123 }
124
125 func encodeEAN13(code string) *utils.BitList {
126 result := new(utils.BitList)
127 result.AddBit(true, false, true)
128
129 var firstNum []bool
130 for cpos, r := range code {
131 num, ok := encoderTable[r]
132 if !ok {
133 return nil
134 }
135 if cpos == 0 {
136 firstNum = num.CheckSum
137 continue
138 }
139
140 var data []bool
141 if cpos < 7 {
142 if firstNum[cpos-1] {
143 data = num.LeftEven
144 } else {
145 data = num.LeftOdd
146 }
147 } else {
148 data = num.Right
149 }
150
151 if cpos == 7 {
152 result.AddBit(false, true, false, true, false)
153 }
154 result.AddBit(data...)
155 }
156 result.AddBit(true, false, true)
157 return result
158 }
159
160
161 func Encode(code string) (barcode.BarcodeIntCS, error) {
162 var checkSum int
163 if len(code) == 7 || len(code) == 12 {
164 code += string(calcCheckNum(code))
165 checkSum = utils.RuneToInt(calcCheckNum(code))
166 } else if len(code) == 8 || len(code) == 13 {
167 check := code[0 : len(code)-1]
168 check += string(calcCheckNum(check))
169 if check != code {
170 return nil, errors.New("checksum missmatch")
171 }
172 checkSum = utils.RuneToInt(rune(code[len(code)-1]))
173 }
174
175 if len(code) == 8 {
176 result := encodeEAN8(code)
177 if result != nil {
178 return utils.New1DCodeIntCheckSum(barcode.TypeEAN8, code, result, checkSum), nil
179 }
180 } else if len(code) == 13 {
181 result := encodeEAN13(code)
182 if result != nil {
183 return utils.New1DCodeIntCheckSum(barcode.TypeEAN13, code, result, checkSum), nil
184 }
185 }
186 return nil, errors.New("invalid ean code data")
187 }
188
View as plain text