barcode/datamatrix/errorcorrection.go

83 lines
2.1 KiB
Go
Raw Normal View History

2013-12-12 19:36:57 +00:00
package datamatrix
import (
"github.com/boombuler/barcode/utils"
)
2013-12-12 19:36:57 +00:00
type errorCorrection struct {
fld *utils.GaloisField
polynomes map[int][]int
2013-12-12 19:36:57 +00:00
}
var ec *errorCorrection = newErrorCorrection()
2013-12-12 19:36:57 +00:00
func newErrorCorrection() *errorCorrection {
result := new(errorCorrection)
result.fld = utils.NewGaloisField(301)
result.polynomes = make(map[int][]int)
return result
2013-12-12 19:36:57 +00:00
}
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
2013-12-12 19:36:57 +00:00
}
return poly
}
func (ec *errorCorrection) calcECCBlock(data []byte, poly []int) []byte {
ecc := make([]byte, len(poly)+1)
2013-12-12 19:36:57 +00:00
for i := 0; i < len(data); i++ {
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])))
2013-12-12 19:36:57 +00:00
}
}
return ecc
2013-12-12 19:36:57 +00:00
}
func (ec *errorCorrection) calcECC(data []byte, size *dmCodeSize) []byte {
2013-12-12 19:36:57 +00:00
buff := make([]byte, size.DataCodewordsPerBlock())
poly := ec.getPolynomial(size.ErrorCorrectionCodewordsPerBlock())
2013-12-12 19:36:57 +00:00
dataSize := len(data)
// make some space for error correction codes
data = append(data, make([]byte, size.ECCCount)...)
2013-12-12 19:36:57 +00:00
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++
2013-12-12 19:36:57 +00:00
}
// 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++
2013-12-12 19:36:57 +00:00
}
}
return data
}