Kaynağa Gözat

bugfix for datamatrix error correction

more tests and code cleanup
Florian Sundermann 12 yıl önce
ebeveyn
işleme
e5d11acdbf

+ 3 - 2
code39/code.go

@@ -2,17 +2,18 @@ package code39
 
 
 import (
 import (
 	"github.com/boombuler/barcode"
 	"github.com/boombuler/barcode"
+	"github.com/boombuler/barcode/utils"
 	"image"
 	"image"
 	"image/color"
 	"image/color"
 )
 )
 
 
 type code struct {
 type code struct {
-	*barcode.BitList
+	*utils.BitList
 	content string
 	content string
 }
 }
 
 
 func newCode() *code {
 func newCode() *code {
-	return &code{&barcode.BitList{}, ""}
+	return &code{new(utils.BitList), ""}
 }
 }
 
 
 func (c *code) Content() string {
 func (c *code) Content() string {

+ 5 - 5
datamatrix/codelayout.go

@@ -1,21 +1,21 @@
 package datamatrix
 package datamatrix
 
 
 import (
 import (
-	"github.com/boombuler/barcode"
+	"github.com/boombuler/barcode/utils"
 )
 )
 
 
 type setValFunc func(byte)
 type setValFunc func(byte)
 
 
 type codeLayout struct {
 type codeLayout struct {
-	matrix *barcode.BitList
-	occupy *barcode.BitList
+	matrix *utils.BitList
+	occupy *utils.BitList
 	size   *dmCodeSize
 	size   *dmCodeSize
 }
 }
 
 
 func newCodeLayout(size *dmCodeSize) *codeLayout {
 func newCodeLayout(size *dmCodeSize) *codeLayout {
 	result := new(codeLayout)
 	result := new(codeLayout)
-	result.matrix = barcode.NewBitList(size.MatrixColumns() * size.MatrixRows())
-	result.occupy = barcode.NewBitList(size.MatrixColumns() * size.MatrixRows())
+	result.matrix = utils.NewBitList(size.MatrixColumns() * size.MatrixRows())
+	result.occupy = utils.NewBitList(size.MatrixColumns() * size.MatrixRows())
 	result.size = size
 	result.size = size
 	return result
 	return result
 }
 }

+ 3 - 2
datamatrix/datamatrixcode.go

@@ -2,18 +2,19 @@ package datamatrix
 
 
 import (
 import (
 	"github.com/boombuler/barcode"
 	"github.com/boombuler/barcode"
+	"github.com/boombuler/barcode/utils"
 	"image"
 	"image"
 	"image/color"
 	"image/color"
 )
 )
 
 
 type datamatrixCode struct {
 type datamatrixCode struct {
-	*barcode.BitList
+	*utils.BitList
 	*dmCodeSize
 	*dmCodeSize
 	content string
 	content string
 }
 }
 
 
 func newDataMatrixCode(size *dmCodeSize) *datamatrixCode {
 func newDataMatrixCode(size *dmCodeSize) *datamatrixCode {
-	return &datamatrixCode{barcode.NewBitList(size.Rows * size.Columns), size, ""}
+	return &datamatrixCode{utils.NewBitList(size.Rows * size.Columns), size, ""}
 }
 }
 
 
 func (c *datamatrixCode) Content() string {
 func (c *datamatrixCode) Content() string {

+ 1 - 1
datamatrix/encoder.go

@@ -20,7 +20,7 @@ func Encode(content string) (barcode.Barcode, error) {
 		return nil, errors.New("to much data to encode")
 		return nil, errors.New("to much data to encode")
 	}
 	}
 	data = addPadding(data, size.DataCodewords())
 	data = addPadding(data, size.DataCodewords())
-	data = generateECC(data, size)
+	data = ec.calcECC(data, size)
 	code := render(data, size)
 	code := render(data, size)
 	if code != nil {
 	if code != nil {
 		code.content = content
 		code.content = content

+ 57 - 80
datamatrix/errorcorrection.go

@@ -1,103 +1,80 @@
 package datamatrix
 package datamatrix
 
 
-// a more generic way would be great!
-// like qr.galoisField with 301
+import (
+	"github.com/boombuler/barcode/utils"
+)
 
 
-var gf_log []int = []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,
+type errorCorrection struct {
+	fld       *utils.GaloisField
+	polynomes map[int][]int
 }
 }
 
 
-var gf_alog []int = []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,
-}
+var ec *errorCorrection = newErrorCorrection()
 
 
-var gf_polys map[int][]int = map[int][]int{
-	5:  []int{228, 48, 15, 111, 62},
-	7:  []int{23, 68, 144, 134, 240, 92, 254},
-	10: []int{28, 24, 185, 166, 223, 248, 116, 255, 110, 61},
-	11: []int{175, 138, 205, 12, 194, 168, 39, 245, 60, 97, 120},
-	12: []int{41, 153, 158, 91, 61, 42, 142, 213, 97, 178, 100, 242},
-	14: []int{156, 97, 192, 252, 95, 9, 157, 119, 138, 45, 18, 186, 83, 185},
-	18: []int{83, 195, 100, 39, 188, 75, 66, 61, 241, 213, 109, 129, 94, 254, 225, 48, 90, 188},
-	20: []int{15, 195, 244, 9, 233, 71, 168, 2, 188, 160, 153, 145, 253, 79, 108, 82, 27, 174, 186, 172},
-	24: []int{52, 190, 88, 205, 109, 39, 176, 21, 155, 197, 251, 223, 155, 21, 5, 172, 254, 124, 12, 181, 184, 96, 50, 193},
-	28: []int{211, 231, 43, 97, 71, 96, 103, 174, 37, 151, 170, 53, 75, 34, 249, 121, 17, 138, 110, 213, 141, 136, 120, 151, 233, 168, 93, 255},
-	36: []int{245, 127, 242, 218, 130, 250, 162, 181, 102, 120, 84, 179, 220, 251, 80, 182, 229, 18, 2, 4, 68, 33, 101, 137, 95, 119, 115, 44, 175, 184, 59, 25, 225, 98, 81, 112},
-	42: []int{77, 193, 137, 31, 19, 38, 22, 153, 247, 105, 122, 2, 245, 133, 242, 8, 175, 95, 100, 9, 167, 105, 214, 111, 57, 121, 21, 1, 253, 57, 54, 101, 248, 202, 69, 50, 150, 177, 226, 5, 9, 5},
-	48: []int{245, 132, 172, 223, 96, 32, 117, 22, 238, 133, 238, 231, 205, 188, 237, 87, 191, 106, 16, 147, 118, 23, 37, 90, 170, 205, 131, 88, 120, 100, 66, 138, 186, 240, 82, 44, 176, 87, 187, 147, 160, 175, 69, 213, 92, 253, 225, 19},
-	56: []int{175, 9, 223, 238, 12, 17, 220, 208, 100, 29, 175, 170, 230, 192, 215, 235, 150, 159, 36, 223, 38, 200, 132, 54, 228, 146, 218, 234, 117, 203, 29, 232, 144, 238, 22, 150, 201, 117, 62, 207, 164, 13, 137, 245, 127, 67, 247, 28, 155, 43, 203, 107, 233, 53, 143, 46},
-	62: []int{242, 93, 169, 50, 144, 210, 39, 118, 202, 188, 201, 189, 143, 108, 196, 37, 185, 112, 134, 230, 245, 63, 197, 190, 250, 106, 185, 221, 175, 64, 114, 71, 161, 44, 147, 6, 27, 218, 51, 63, 87, 10, 40, 130, 188, 17, 163, 31, 176, 170, 4, 107, 232, 7, 94, 166, 224, 124, 86, 47, 11, 204},
-	68: []int{220, 228, 173, 89, 251, 149, 159, 56, 89, 33, 147, 244, 154, 36, 73, 127, 213, 136, 248, 180, 234, 197, 158, 177, 68, 122, 93, 213, 15, 160, 227, 236, 66, 139, 153, 185, 202, 167, 179, 25, 220, 232, 96, 210, 231, 136, 223, 239, 181, 241, 59, 52, 172, 25, 49, 232, 211, 189, 64, 54, 108, 153, 132, 63, 96, 103, 82, 186},
+func newErrorCorrection() *errorCorrection {
+	result := new(errorCorrection)
+	result.fld = utils.NewGaloisField(301)
+	result.polynomes = make(map[int][]int)
+	return result
 }
 }
 
 
-func rsBlock(data []byte, ncout []byte, poly []int) {
-	for i := 0; i < len(ncout); i++ {
-		ncout[i] = 0
+func (ec *errorCorrection) getPolynomial(count int) []int {
+	poly, ok := ec.polynomes[count]
+	if !ok {
+		idx := 1
+		poly = make([]int, count+1)
+		poly[0] = 1
+		for i := 1; i <= count; i++ {
+			poly[i] = 1
+			for j := i - 1; j > 0; j-- {
+				if poly[j] != 0 {
+					poly[j] = ec.fld.ALogTbl[(int(ec.fld.LogTbl[poly[j]])+idx)%255]
+				}
+				poly[j] = ec.fld.AddOrSub(poly[j], poly[j-1])
+			}
+			poly[0] = ec.fld.ALogTbl[(int(ec.fld.LogTbl[poly[0]])+idx)%255]
+			idx++
+		}
+		poly = poly[0:count]
+		ec.polynomes[count] = poly
 	}
 	}
+	return poly
+}
+
+func (ec *errorCorrection) calcECCBlock(data []byte, poly []int) []byte {
+	ecc := make([]byte, len(poly)+1)
 
 
 	for i := 0; i < len(data); i++ {
 	for i := 0; i < len(data); i++ {
-		k := (ncout[0] ^ data[i]) & 0xff
-		for j := 0; j < len(ncout)-1; j++ {
-			k1 := 0
-			if k != 0 {
-				k1 = gf_alog[(gf_log[k]+gf_log[poly[len(ncout)-j-2]])%255]
-			}
-			ncout[j] = ncout[j+1] ^ byte(k1)
+		k := ec.fld.AddOrSub(int(ecc[0]), int(data[i]))
+		for j := 0; j < len(ecc)-1; j++ {
+			ecc[j] = byte(ec.fld.AddOrSub(int(ecc[j+1]), ec.fld.Multiply(k, poly[len(ecc)-j-2])))
 		}
 		}
 	}
 	}
+	return ecc
 }
 }
 
 
-func generateECC(data []byte, size *dmCodeSize) []byte {
+func (ec *errorCorrection) calcECC(data []byte, size *dmCodeSize) []byte {
 	buff := make([]byte, size.DataCodewordsPerBlock())
 	buff := make([]byte, size.DataCodewordsPerBlock())
-	ecc := make([]byte, size.ErrorCorrectionCodewordsPerBlock()+1)
-	poly := gf_polys[size.ErrorCorrectionCodewordsPerBlock()]
+	poly := ec.getPolynomial(size.ErrorCorrectionCodewordsPerBlock())
 
 
 	dataSize := len(data)
 	dataSize := len(data)
-	// make some space...
-	space := make([]byte, size.ECCCount)
-	data = append(data, space...)
+	// make some space for error correction codes
+	data = append(data, make([]byte, size.ECCCount)...)
 
 
-	for b := 0; b < size.BlockCount; b++ {
-		p := 0
-		for n := b; n < dataSize; n += size.BlockCount {
-			buff[p] = data[n]
-			p++
+	for block := 0; block < size.BlockCount; block++ {
+		// copy the data for the current block to buff
+		j := 0
+		for i := block; i < dataSize; i += size.BlockCount {
+			buff[j] = data[i]
+			j++
 		}
 		}
-		rsBlock(buff, ecc, poly)
-		p = 0
-		for n := b; n < size.ErrorCorrectionCodewordsPerBlock()*size.BlockCount; n += size.BlockCount {
-			data[dataSize+n] = ecc[p]
-			p++
+		// calc the error correction codes
+		ecc := ec.calcECCBlock(buff, poly)
+		// and append them to the result
+		j = 0
+		for i := block; i < size.ErrorCorrectionCodewordsPerBlock()*size.BlockCount; i += size.BlockCount {
+			data[dataSize+i] = ecc[j]
+			j++
 		}
 		}
 	}
 	}
 
 

+ 61 - 0
datamatrix/errorcorrection_test.go

@@ -0,0 +1,61 @@
+package datamatrix
+
+import (
+	"bytes"
+	"testing"
+)
+
+func Test_GetPolynomial(t *testing.T) {
+	var gf_polys map[int][]int = map[int][]int{
+		5:  []int{228, 48, 15, 111, 62},
+		7:  []int{23, 68, 144, 134, 240, 92, 254},
+		10: []int{28, 24, 185, 166, 223, 248, 116, 255, 110, 61},
+		11: []int{175, 138, 205, 12, 194, 168, 39, 245, 60, 97, 120},
+		12: []int{41, 153, 158, 91, 61, 42, 142, 213, 97, 178, 100, 242},
+		14: []int{156, 97, 192, 252, 95, 9, 157, 119, 138, 45, 18, 186, 83, 185},
+		18: []int{83, 195, 100, 39, 188, 75, 66, 61, 241, 213, 109, 129, 94, 254, 225, 48, 90, 188},
+		20: []int{15, 195, 244, 9, 233, 71, 168, 2, 188, 160, 153, 145, 253, 79, 108, 82, 27, 174, 186, 172},
+		24: []int{52, 190, 88, 205, 109, 39, 176, 21, 155, 197, 251, 223, 155, 21, 5, 172, 254, 124, 12, 181, 184, 96, 50, 193},
+		28: []int{211, 231, 43, 97, 71, 96, 103, 174, 37, 151, 170, 53, 75, 34, 249, 121, 17, 138, 110, 213, 141, 136, 120, 151, 233, 168, 93, 255},
+		36: []int{245, 127, 242, 218, 130, 250, 162, 181, 102, 120, 84, 179, 220, 251, 80, 182, 229, 18, 2, 4, 68, 33, 101, 137, 95, 119, 115, 44, 175, 184, 59, 25, 225, 98, 81, 112},
+		42: []int{77, 193, 137, 31, 19, 38, 22, 153, 247, 105, 122, 2, 245, 133, 242, 8, 175, 95, 100, 9, 167, 105, 214, 111, 57, 121, 21, 1, 253, 57, 54, 101, 248, 202, 69, 50, 150, 177, 226, 5, 9, 5},
+		48: []int{245, 132, 172, 223, 96, 32, 117, 22, 238, 133, 238, 231, 205, 188, 237, 87, 191, 106, 16, 147, 118, 23, 37, 90, 170, 205, 131, 88, 120, 100, 66, 138, 186, 240, 82, 44, 176, 87, 187, 147, 160, 175, 69, 213, 92, 253, 225, 19},
+		56: []int{175, 9, 223, 238, 12, 17, 220, 208, 100, 29, 175, 170, 230, 192, 215, 235, 150, 159, 36, 223, 38, 200, 132, 54, 228, 146, 218, 234, 117, 203, 29, 232, 144, 238, 22, 150, 201, 117, 62, 207, 164, 13, 137, 245, 127, 67, 247, 28, 155, 43, 203, 107, 233, 53, 143, 46},
+		62: []int{242, 93, 169, 50, 144, 210, 39, 118, 202, 188, 201, 189, 143, 108, 196, 37, 185, 112, 134, 230, 245, 63, 197, 190, 250, 106, 185, 221, 175, 64, 114, 71, 161, 44, 147, 6, 27, 218, 51, 63, 87, 10, 40, 130, 188, 17, 163, 31, 176, 170, 4, 107, 232, 7, 94, 166, 224, 124, 86, 47, 11, 204},
+		68: []int{220, 228, 173, 89, 251, 149, 159, 56, 89, 33, 147, 244, 154, 36, 73, 127, 213, 136, 248, 180, 234, 197, 158, 177, 68, 122, 93, 213, 15, 160, 227, 236, 66, 139, 153, 185, 202, 167, 179, 25, 220, 232, 96, 210, 231, 136, 223, 239, 181, 241, 59, 52, 172, 25, 49, 232, 211, 189, 64, 54, 108, 153, 132, 63, 96, 103, 82, 186},
+	}
+
+	for i, tst := range gf_polys {
+		res := ec.getPolynomial(i)
+		if len(res) != len(tst) {
+			t.Fail()
+		}
+		for i := 0; i < len(res); i++ {
+			if res[i] != tst[i] {
+				t.Fail()
+			}
+		}
+	}
+}
+
+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")
+	}
+}

+ 3 - 2
ean/eancode.go

@@ -2,12 +2,13 @@ package ean
 
 
 import (
 import (
 	"github.com/boombuler/barcode"
 	"github.com/boombuler/barcode"
+	"github.com/boombuler/barcode/utils"
 	"image"
 	"image"
 	"image/color"
 	"image/color"
 )
 )
 
 
 type eancode struct {
 type eancode struct {
-	*barcode.BitList
+	*utils.BitList
 	content string
 	content string
 }
 }
 
 
@@ -16,7 +17,7 @@ func newEANCode(isEAN8 bool) *eancode {
 	if isEAN8 {
 	if isEAN8 {
 		capacity = 67
 		capacity = 67
 	}
 	}
-	return &eancode{barcode.NewBitList(capacity), ""}
+	return &eancode{utils.NewBitList(capacity), ""}
 }
 }
 
 
 func (c *eancode) Content() string {
 func (c *eancode) Content() string {

+ 3 - 3
qr/alphanumeric.go

@@ -3,7 +3,7 @@ package qr
 import (
 import (
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
-	"github.com/boombuler/barcode"
+	"github.com/boombuler/barcode/utils"
 	"strings"
 	"strings"
 )
 )
 
 
@@ -25,7 +25,7 @@ func stringToAlphaIdx(content string) <-chan int {
 	return result
 	return result
 }
 }
 
 
-func encodeAlphaNumeric(content string, ecl ErrorCorrectionLevel) (*barcode.BitList, *versionInfo, error) {
+func encodeAlphaNumeric(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) {
 
 
 	contentLenIsOdd := len(content)%2 == 1
 	contentLenIsOdd := len(content)%2 == 1
 	contentBitCount := (len(content) / 2) * 11
 	contentBitCount := (len(content) / 2) * 11
@@ -37,7 +37,7 @@ func encodeAlphaNumeric(content string, ecl ErrorCorrectionLevel) (*barcode.BitL
 		return nil, nil, errors.New("To much data to encode")
 		return nil, nil, errors.New("To much data to encode")
 	}
 	}
 
 
-	res := new(barcode.BitList)
+	res := new(utils.BitList)
 	res.AddBits(int(alphaNumericMode), 4)
 	res.AddBits(int(alphaNumericMode), 4)
 	res.AddBits(len(content), vi.charCountBits(alphaNumericMode))
 	res.AddBits(len(content), vi.charCountBits(alphaNumericMode))
 
 

+ 2 - 2
qr/automatic.go

@@ -2,10 +2,10 @@ package qr
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"github.com/boombuler/barcode"
+	"github.com/boombuler/barcode/utils"
 )
 )
 
 
-func encodeAuto(content string, ecl ErrorCorrectionLevel) (*barcode.BitList, *versionInfo, error) {
+func encodeAuto(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) {
 	bits, vi, _ := Numeric.getEncoder()(content, ecl)
 	bits, vi, _ := Numeric.getEncoder()(content, ecl)
 	if bits != nil && vi != nil {
 	if bits != nil && vi != nil {
 		return bits, vi, nil
 		return bits, vi, nil

+ 2 - 2
qr/blocks.go

@@ -15,7 +15,7 @@ func splitToBlocks(data <-chan byte, vi *versionInfo) blockList {
 		for cw := 0; cw < int(vi.DataCodeWordsPerBlockInGroup1); cw++ {
 		for cw := 0; cw < int(vi.DataCodeWordsPerBlockInGroup1); cw++ {
 			blk.data[cw] = <-data
 			blk.data[cw] = <-data
 		}
 		}
-		blk.ecc = gf.calcECC(blk.data, vi.ErrorCorrectionCodewordsPerBlock)
+		blk.ecc = ec.calcECC(blk.data, vi.ErrorCorrectionCodewordsPerBlock)
 		result[b] = blk
 		result[b] = blk
 	}
 	}
 
 
@@ -25,7 +25,7 @@ func splitToBlocks(data <-chan byte, vi *versionInfo) blockList {
 		for cw := 0; cw < int(vi.DataCodeWordsPerBlockInGroup2); cw++ {
 		for cw := 0; cw < int(vi.DataCodeWordsPerBlockInGroup2); cw++ {
 			blk.data[cw] = <-data
 			blk.data[cw] = <-data
 		}
 		}
-		blk.ecc = gf.calcECC(blk.data, vi.ErrorCorrectionCodewordsPerBlock)
+		blk.ecc = ec.calcECC(blk.data, vi.ErrorCorrectionCodewordsPerBlock)
 		result[int(vi.NumberOfBlocksInGroup1)+b] = blk
 		result[int(vi.NumberOfBlocksInGroup1)+b] = blk
 	}
 	}
 
 

+ 3 - 2
qr/encoder.go

@@ -4,10 +4,11 @@ package qr
 import (
 import (
 	"fmt"
 	"fmt"
 	"github.com/boombuler/barcode"
 	"github.com/boombuler/barcode"
+	"github.com/boombuler/barcode/utils"
 	"image"
 	"image"
 )
 )
 
 
-type encodeFn func(content string, eccLevel ErrorCorrectionLevel) (*barcode.BitList, *versionInfo, error)
+type encodeFn func(content string, eccLevel ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error)
 
 
 type Encoding byte
 type Encoding byte
 
 
@@ -463,7 +464,7 @@ func drawVersionInfo(vi *versionInfo, set func(int, int, bool)) {
 
 
 }
 }
 
 
-func addPaddingAndTerminator(bl *barcode.BitList, vi *versionInfo) {
+func addPaddingAndTerminator(bl *utils.BitList, vi *versionInfo) {
 	for i := 0; i < 4 && bl.Len() < vi.totalDataBytes()*8; i++ {
 	for i := 0; i < 4 && bl.Len() < vi.totalDataBytes()*8; i++ {
 		bl.AddBit(false)
 		bl.AddBit(false)
 	}
 	}

+ 22 - 39
qr/errorcorrection.go

@@ -1,73 +1,56 @@
 package qr
 package qr
 
 
-type galoisField struct {
-	aLogTbl   []byte
-	logTbl    []byte
+import (
+	"github.com/boombuler/barcode/utils"
+)
+
+type errorCorrection struct {
+	fld       *utils.GaloisField
 	polynomes map[byte][]byte
 	polynomes map[byte][]byte
 }
 }
 
 
-var gf *galoisField = newGF()
-
-func newGF() *galoisField {
-	result := new(galoisField)
-	result.polynomes = make(map[byte][]byte)
-	result.aLogTbl = make([]byte, 255)
-	result.logTbl = make([]byte, 256)
-
-	result.aLogTbl[0] = 1
-
-	x := 1
-	for i := 1; i < 255; i++ {
-		x = x * 2
-		if x > 255 {
-			x = x ^ 285
-		}
-		result.aLogTbl[i] = byte(x)
-	}
-
-	for i := 1; i < 255; i++ {
-		result.logTbl[result.aLogTbl[i]] = byte(i)
-	}
+var ec *errorCorrection = newGF()
 
 
-	return result
+func newGF() *errorCorrection {
+	return &errorCorrection{utils.NewGaloisField(285), make(map[byte][]byte)}
 }
 }
 
 
-func (gf *galoisField) getPolynom(eccc byte) []byte {
-	_, ok := gf.polynomes[eccc]
+func (ec *errorCorrection) getPolynomial(eccc byte) []byte {
+	_, ok := ec.polynomes[eccc]
 	if !ok {
 	if !ok {
 		if eccc == 1 {
 		if eccc == 1 {
-			gf.polynomes[eccc] = []byte{0, 0}
+			ec.polynomes[eccc] = []byte{0, 0}
 		} else {
 		} else {
-			b1 := gf.getPolynom(eccc - 1)
+			b1 := ec.getPolynomial(eccc - 1)
 			result := make([]byte, eccc+1)
 			result := make([]byte, eccc+1)
 			for x := 0; x < len(b1); x++ {
 			for x := 0; x < len(b1); x++ {
 				tmp1 := (int(b1[x]) + int(eccc-1)) % 255
 				tmp1 := (int(b1[x]) + int(eccc-1)) % 255
 				if x == 0 {
 				if x == 0 {
 					result[x] = b1[x]
 					result[x] = b1[x]
 				} else {
 				} else {
-					tmp0 := int(gf.aLogTbl[result[x]]) ^ int(gf.aLogTbl[b1[x]])
-					result[x] = gf.logTbl[tmp0]
+					tmp0 := int(ec.fld.ALogTbl[result[x]]) ^ int(ec.fld.ALogTbl[b1[x]])
+					result[x] = byte(ec.fld.LogTbl[tmp0])
 				}
 				}
 				result[x+1] = byte(tmp1)
 				result[x+1] = byte(tmp1)
 			}
 			}
-			gf.polynomes[eccc] = result
+			ec.polynomes[eccc] = result
 
 
 		}
 		}
 	}
 	}
-	return gf.polynomes[eccc]
+	return ec.polynomes[eccc]
 }
 }
 
 
-func (gf *galoisField) calcECC(data []byte, eccCount byte) []byte {
+func (ec *errorCorrection) calcECC(data []byte, eccCount byte) []byte {
 	tmp := make([]byte, len(data)+int(eccCount))
 	tmp := make([]byte, len(data)+int(eccCount))
 	copy(tmp, data)
 	copy(tmp, data)
-	generator := gf.getPolynom(eccCount)
+	generator := ec.getPolynomial(eccCount)
 
 
 	for i := 0; i < len(data); i++ {
 	for i := 0; i < len(data); i++ {
-		alpha := gf.logTbl[tmp[i]]
+		alpha := ec.fld.LogTbl[tmp[i]]
 		for j := 0; j < len(generator); j++ {
 		for j := 0; j < len(generator); j++ {
 			idx := (int(alpha) + int(generator[j])) % 255
 			idx := (int(alpha) + int(generator[j])) % 255
-			polyJ := gf.aLogTbl[idx]
-			tmp[i+j] = (tmp[i+j] ^ polyJ)
+			polyJ := ec.fld.ALogTbl[idx]
+			tmp[i+j] = byte(ec.fld.AddOrSub(int(tmp[i+j]), polyJ))
 		}
 		}
 	}
 	}
 
 

+ 7 - 7
qr/errorcorrection_test.go

@@ -7,22 +7,22 @@ import (
 
 
 func Test_LogTables(t *testing.T) {
 func Test_LogTables(t *testing.T) {
 	for i := 1; i <= 255; i++ {
 	for i := 1; i <= 255; i++ {
-		tmp := gf.logTbl[i]
-		if byte(i) != gf.aLogTbl[tmp] {
+		tmp := ec.fld.LogTbl[i]
+		if i != ec.fld.ALogTbl[tmp] {
 			t.Errorf("Invalid LogTables: %d", i)
 			t.Errorf("Invalid LogTables: %d", i)
 		}
 		}
 	}
 	}
 
 
-	if gf.aLogTbl[11] != 232 || gf.aLogTbl[87] != 127 || gf.aLogTbl[225] != 36 {
+	if ec.fld.ALogTbl[11] != 232 || ec.fld.ALogTbl[87] != 127 || ec.fld.ALogTbl[225] != 36 {
 		t.Fail()
 		t.Fail()
 	}
 	}
 }
 }
 
 
-func Test_Polynoms(t *testing.T) {
+func Test_GetPolynomial(t *testing.T) {
 	doTest := func(b []byte) {
 	doTest := func(b []byte) {
 		cnt := byte(len(b) - 1)
 		cnt := byte(len(b) - 1)
-		if bytes.Compare(gf.getPolynom(cnt), b) != 0 {
-			t.Errorf("Failed getPolynom(%d)", cnt)
+		if bytes.Compare(ec.getPolynomial(cnt), b) != 0 {
+			t.Errorf("Failed getPolynomial(%d)", cnt)
 		}
 		}
 	}
 	}
 	doTest([]byte{0, 0})
 	doTest([]byte{0, 0})
@@ -34,7 +34,7 @@ func Test_Polynoms(t *testing.T) {
 func Test_ErrorCorrection(t *testing.T) {
 func Test_ErrorCorrection(t *testing.T) {
 	doTest := func(b []byte, ecc []byte) {
 	doTest := func(b []byte, ecc []byte) {
 		cnt := byte(len(ecc))
 		cnt := byte(len(ecc))
-		if bytes.Compare(gf.calcECC(b, cnt), ecc) != 0 {
+		if bytes.Compare(ec.calcECC(b, cnt), ecc) != 0 {
 			t.Fail()
 			t.Fail()
 		}
 		}
 	}
 	}

+ 3 - 3
qr/numeric.go

@@ -3,11 +3,11 @@ package qr
 import (
 import (
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
-	"github.com/boombuler/barcode"
+	"github.com/boombuler/barcode/utils"
 	"strconv"
 	"strconv"
 )
 )
 
 
-func encodeNumeric(content string, ecl ErrorCorrectionLevel) (*barcode.BitList, *versionInfo, error) {
+func encodeNumeric(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) {
 	contentBitCount := (len(content) / 3) * 10
 	contentBitCount := (len(content) / 3) * 10
 	switch len(content) % 3 {
 	switch len(content) % 3 {
 	case 1:
 	case 1:
@@ -19,7 +19,7 @@ func encodeNumeric(content string, ecl ErrorCorrectionLevel) (*barcode.BitList,
 	if vi == nil {
 	if vi == nil {
 		return nil, nil, errors.New("To much data to encode")
 		return nil, nil, errors.New("To much data to encode")
 	}
 	}
-	res := new(barcode.BitList)
+	res := new(utils.BitList)
 	res.AddBits(int(numericMode), 4)
 	res.AddBits(int(numericMode), 4)
 	res.AddBits(len(content), vi.charCountBits(numericMode))
 	res.AddBits(len(content), vi.charCountBits(numericMode))
 
 

+ 3 - 2
qr/qrcode.go

@@ -2,6 +2,7 @@ package qr
 
 
 import (
 import (
 	"github.com/boombuler/barcode"
 	"github.com/boombuler/barcode"
+	"github.com/boombuler/barcode/utils"
 	"image"
 	"image"
 	"image/color"
 	"image/color"
 	"math"
 	"math"
@@ -9,7 +10,7 @@ import (
 
 
 type qrcode struct {
 type qrcode struct {
 	dimension int
 	dimension int
-	data      *barcode.BitList
+	data      *utils.BitList
 	content   string
 	content   string
 }
 }
 
 
@@ -159,6 +160,6 @@ func (qr *qrcode) calcPenaltyRule4() uint {
 func newBarcode(dim int) *qrcode {
 func newBarcode(dim int) *qrcode {
 	res := new(qrcode)
 	res := new(qrcode)
 	res.dimension = dim
 	res.dimension = dim
-	res.data = barcode.NewBitList(dim * dim)
+	res.data = utils.NewBitList(dim * dim)
 	return res
 	return res
 }
 }

+ 3 - 3
qr/unicode.go

@@ -2,10 +2,10 @@ package qr
 
 
 import (
 import (
 	"errors"
 	"errors"
-	"github.com/boombuler/barcode"
+	"github.com/boombuler/barcode/utils"
 )
 )
 
 
-func encodeUnicode(content string, ecl ErrorCorrectionLevel) (*barcode.BitList, *versionInfo, error) {
+func encodeUnicode(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) {
 	data := []byte(content)
 	data := []byte(content)
 
 
 	vi := findSmallestVersionInfo(ecl, byteMode, len(data)*8)
 	vi := findSmallestVersionInfo(ecl, byteMode, len(data)*8)
@@ -15,7 +15,7 @@ func encodeUnicode(content string, ecl ErrorCorrectionLevel) (*barcode.BitList,
 
 
 	// It's not correct to add the unicode bytes to the result directly but most readers can't handle the
 	// It's not correct to add the unicode bytes to the result directly but most readers can't handle the
 	// required ECI header...
 	// required ECI header...
-	res := new(barcode.BitList)
+	res := new(utils.BitList)
 	res.AddBits(int(byteMode), 4)
 	res.AddBits(int(byteMode), 4)
 	res.AddBits(len(content), vi.charCountBits(byteMode))
 	res.AddBits(len(content), vi.charCountBits(byteMode))
 	for _, b := range data {
 	for _, b := range data {

+ 1 - 1
bitlist.go → utils/bitlist.go

@@ -1,4 +1,4 @@
-package barcode
+package utils
 
 
 // utility class that contains bits
 // utility class that contains bits
 type BitList struct {
 type BitList struct {

+ 49 - 0
utils/galoisfield.go

@@ -0,0 +1,49 @@
+package utils
+
+type GaloisField struct {
+	ALogTbl []int
+	LogTbl  []int
+}
+
+func NewGaloisField(pp int) *GaloisField {
+	result := new(GaloisField)
+	fldSize := 256
+
+	result.ALogTbl = make([]int, fldSize)
+	result.LogTbl = make([]int, fldSize)
+
+	x := 1
+	for i := 0; i < fldSize; i++ {
+		result.ALogTbl[i] = x
+		x = x * 2
+		if x >= fldSize {
+			x = (x ^ pp) & (fldSize - 1)
+		}
+	}
+
+	for i := 0; i < fldSize; i++ {
+		result.LogTbl[result.ALogTbl[i]] = int(i)
+	}
+
+	return result
+}
+
+func (gf *GaloisField) AddOrSub(a, b int) int {
+	return a ^ b
+}
+
+func (gf *GaloisField) Multiply(a, b int) int {
+	if a == 0 || b == 0 {
+		return 0
+	}
+	return gf.ALogTbl[(gf.LogTbl[a]+gf.LogTbl[b])%255]
+}
+
+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])%255]
+}

+ 59 - 0
utils/galoisfield_test.go

@@ -0,0 +1,59 @@
+package 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)
+	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")
+		}
+	}
+
+}