errorcorrection.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. package datamatrix
  2. import (
  3. "github.com/boombuler/barcode/utils"
  4. )
  5. type errorCorrection struct {
  6. fld *utils.GaloisField
  7. polynomes map[int][]int
  8. }
  9. var ec *errorCorrection = newErrorCorrection()
  10. func newErrorCorrection() *errorCorrection {
  11. result := new(errorCorrection)
  12. result.fld = utils.NewGaloisField(301)
  13. result.polynomes = make(map[int][]int)
  14. return result
  15. }
  16. func (ec *errorCorrection) getPolynomial(count int) []int {
  17. poly, ok := ec.polynomes[count]
  18. if !ok {
  19. idx := 1
  20. poly = make([]int, count+1)
  21. poly[0] = 1
  22. for i := 1; i <= count; i++ {
  23. poly[i] = 1
  24. for j := i - 1; j > 0; j-- {
  25. if poly[j] != 0 {
  26. poly[j] = ec.fld.ALogTbl[(int(ec.fld.LogTbl[poly[j]])+idx)%255]
  27. }
  28. poly[j] = ec.fld.AddOrSub(poly[j], poly[j-1])
  29. }
  30. poly[0] = ec.fld.ALogTbl[(int(ec.fld.LogTbl[poly[0]])+idx)%255]
  31. idx++
  32. }
  33. poly = poly[0:count]
  34. ec.polynomes[count] = poly
  35. }
  36. return poly
  37. }
  38. func (ec *errorCorrection) calcECCBlock(data []byte, poly []int) []byte {
  39. ecc := make([]byte, len(poly)+1)
  40. for i := 0; i < len(data); i++ {
  41. k := ec.fld.AddOrSub(int(ecc[0]), int(data[i]))
  42. for j := 0; j < len(ecc)-1; j++ {
  43. ecc[j] = byte(ec.fld.AddOrSub(int(ecc[j+1]), ec.fld.Multiply(k, poly[len(ecc)-j-2])))
  44. }
  45. }
  46. return ecc
  47. }
  48. func (ec *errorCorrection) calcECC(data []byte, size *dmCodeSize) []byte {
  49. poly := ec.getPolynomial(size.ErrorCorrectionCodewordsPerBlock())
  50. dataSize := len(data)
  51. // make some space for error correction codes
  52. data = append(data, make([]byte, size.ECCCount)...)
  53. for block := 0; block < size.BlockCount; block++ {
  54. dataCnt := size.DataCodewordsForBlock(block)
  55. buff := make([]byte, dataCnt)
  56. // copy the data for the current block to buff
  57. j := 0
  58. for i := block; i < dataSize; i += size.BlockCount {
  59. buff[j] = data[i]
  60. j++
  61. }
  62. // calc the error correction codes
  63. ecc := ec.calcECCBlock(buff, poly)
  64. // and append them to the result
  65. j = 0
  66. for i := block; i < size.ErrorCorrectionCodewordsPerBlock()*size.BlockCount; i += size.BlockCount {
  67. data[dataSize+i] = ecc[j]
  68. j++
  69. }
  70. }
  71. return data
  72. }