bugfix for datamatrix error correction

more tests and code cleanup
This commit is contained in:
Florian Sundermann committed 2013-12-13 13:53:27 +01:00
1 parent e754f1b44c
commit e5d11acdbf
19 files changed
+291 -157

No files matched your search

+3 -3
View File
@@ -3,7 +3,7 @@ package qr
import (
"errors"
"fmt"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
"strings"
)
@@ -25,7 +25,7 @@ func stringToAlphaIdx(content string) <-chan int {
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
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")
}
res := new(barcode.BitList)
res := new(utils.BitList)
res.AddBits(int(alphaNumericMode), 4)
res.AddBits(len(content), vi.charCountBits(alphaNumericMode))
+2 -2
View File
@@ -2,10 +2,10 @@ package qr
import (
"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)
if bits != nil && vi != nil {
return bits, vi, nil
+2 -2
View File
@@ -15,7 +15,7 @@ func splitToBlocks(data <-chan byte, vi *versionInfo) blockList {
for cw := 0; cw < int(vi.DataCodeWordsPerBlockInGroup1); cw++ {
blk.data[cw] = <-data
}
blk.ecc = gf.calcECC(blk.data, vi.ErrorCorrectionCodewordsPerBlock)
blk.ecc = ec.calcECC(blk.data, vi.ErrorCorrectionCodewordsPerBlock)
result[b] = blk
}
@@ -25,7 +25,7 @@ func splitToBlocks(data <-chan byte, vi *versionInfo) blockList {
for cw := 0; cw < int(vi.DataCodeWordsPerBlockInGroup2); cw++ {
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
}
+3 -2
View File
@@ -4,10 +4,11 @@ package qr
import (
"fmt"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
"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
@@ -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++ {
bl.AddBit(false)
}
+22 -39
View File
@@ -1,73 +1,56 @@
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
}
var gf *galoisField = newGF()
var ec *errorCorrection = 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)
}
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 eccc == 1 {
gf.polynomes[eccc] = []byte{0, 0}
ec.polynomes[eccc] = []byte{0, 0}
} else {
b1 := gf.getPolynom(eccc - 1)
b1 := ec.getPolynomial(eccc - 1)
result := make([]byte, eccc+1)
for x := 0; x < len(b1); x++ {
tmp1 := (int(b1[x]) + int(eccc-1)) % 255
if x == 0 {
result[x] = b1[x]
} 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)
}
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))
copy(tmp, data)
generator := gf.getPolynom(eccCount)
generator := ec.getPolynomial(eccCount)
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++ {
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
View File
@@ -7,22 +7,22 @@ import (
func Test_LogTables(t *testing.T) {
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)
}
}
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()
}
}
func Test_Polynoms(t *testing.T) {
func Test_GetPolynomial(t *testing.T) {
doTest := func(b []byte) {
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})
@@ -34,7 +34,7 @@ func Test_Polynoms(t *testing.T) {
func Test_ErrorCorrection(t *testing.T) {
doTest := func(b []byte, ecc []byte) {
cnt := byte(len(ecc))
if bytes.Compare(gf.calcECC(b, cnt), ecc) != 0 {
if bytes.Compare(ec.calcECC(b, cnt), ecc) != 0 {
t.Fail()
}
}
+3 -3
View File
@@ -3,11 +3,11 @@ package qr
import (
"errors"
"fmt"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
"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
switch len(content) % 3 {
case 1:
@@ -19,7 +19,7 @@ func encodeNumeric(content string, ecl ErrorCorrectionLevel) (*barcode.BitList,
if vi == nil {
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(len(content), vi.charCountBits(numericMode))
+3 -2
View File
@@ -2,6 +2,7 @@ package qr
import (
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
"image"
"image/color"
"math"
@@ -9,7 +10,7 @@ import (
type qrcode struct {
dimension int
data *barcode.BitList
data *utils.BitList
content string
}
@@ -159,6 +160,6 @@ func (qr *qrcode) calcPenaltyRule4() uint {
func newBarcode(dim int) *qrcode {
res := new(qrcode)
res.dimension = dim
res.data = barcode.NewBitList(dim * dim)
res.data = utils.NewBitList(dim * dim)
return res
}
+3 -3
View File
@@ -2,10 +2,10 @@ package qr
import (
"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)
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
// required ECI header...
res := new(barcode.BitList)
res := new(utils.BitList)
res.AddBits(int(byteMode), 4)
res.AddBits(len(content), vi.charCountBits(byteMode))
for _, b := range data {