libdmtx 0.7.8.7
libdmtx is a software library that enables programs to read and write Data Matrix barcodes of the modern ECC200 variety.
Loading...
Searching...
No Matches
dmtxreedsol.c
Go to the documentation of this file.
1
21#include <assert.h>
22
23#include "dmtx.h"
24#include "dmtxstatic.h"
25
26#define NN 255
27#define MAX_ERROR_WORD_COUNT 68
28
29#define DMTX_CHECK_BOUNDS(l, i) DmtxAssert((i) >= 0 && (i) < (l)->length && (l)->length <= (l)->capacity)
30
31/* GF add (a + b) */
32#define GfAdd(a, b) ((a) ^ (b))
33
34/* GF multiply (a * b) */
35#define GfMult(a, b) (((a) == 0 || (b) == 0) ? 0 : antilog301[(log301[(a)] + log301[(b)]) % NN])
36
37/* GF multiply by antilog (a * alpha**b) */
38#define GfMultAntilog(a, b) (((a) == 0) ? 0 : antilog301[(log301[(a)] + (b)) % NN])
39
40/* GF(256) log values using primitive polynomial 301 */
41static DmtxByte log301[] = {
42 255, 0, 1, 240, 2, 225, 241, 53, 3, 38, 226, 133, 242, 43, 54, 210, 4, 195, 39, 114, 227, 106,
43 134, 28, 243, 140, 44, 23, 55, 118, 211, 234, 5, 219, 196, 96, 40, 222, 115, 103, 228, 78, 107, 125,
44 135, 8, 29, 162, 244, 186, 141, 180, 45, 99, 24, 49, 56, 13, 119, 153, 212, 199, 235, 91, 6, 76,
45 220, 217, 197, 11, 97, 184, 41, 36, 223, 253, 116, 138, 104, 193, 229, 86, 79, 171, 108, 165, 126, 145,
46 136, 34, 9, 74, 30, 32, 163, 84, 245, 173, 187, 204, 142, 81, 181, 190, 46, 88, 100, 159, 25, 231,
47 50, 207, 57, 147, 14, 67, 120, 128, 154, 248, 213, 167, 200, 63, 236, 110, 92, 176, 7, 161, 77, 124,
48 221, 102, 218, 95, 198, 90, 12, 152, 98, 48, 185, 179, 42, 209, 37, 132, 224, 52, 254, 239, 117, 233,
49 139, 22, 105, 27, 194, 113, 230, 206, 87, 158, 80, 189, 172, 203, 109, 175, 166, 62, 127, 247, 146, 66,
50 137, 192, 35, 252, 10, 183, 75, 216, 31, 83, 33, 73, 164, 144, 85, 170, 246, 65, 174, 61, 188, 202,
51 205, 157, 143, 169, 82, 72, 182, 215, 191, 251, 47, 178, 89, 151, 101, 94, 160, 123, 26, 112, 232, 21,
52 51, 238, 208, 131, 58, 69, 148, 18, 15, 16, 68, 17, 121, 149, 129, 19, 155, 59, 249, 70, 214, 250,
53 168, 71, 201, 156, 64, 60, 237, 130, 111, 20, 93, 122, 177, 150};
54
55/* GF(256) antilog values using primitive polynomial 301 */
56static DmtxByte antilog301[] = {
57 1, 2, 4, 8, 16, 32, 64, 128, 45, 90, 180, 69, 138, 57, 114, 228, 229, 231, 227, 235, 251, 219,
58 155, 27, 54, 108, 216, 157, 23, 46, 92, 184, 93, 186, 89, 178, 73, 146, 9, 18, 36, 72, 144, 13,
59 26, 52, 104, 208, 141, 55, 110, 220, 149, 7, 14, 28, 56, 112, 224, 237, 247, 195, 171, 123, 246, 193,
60 175, 115, 230, 225, 239, 243, 203, 187, 91, 182, 65, 130, 41, 82, 164, 101, 202, 185, 95, 190, 81, 162,
61 105, 210, 137, 63, 126, 252, 213, 135, 35, 70, 140, 53, 106, 212, 133, 39, 78, 156, 21, 42, 84, 168,
62 125, 250, 217, 159, 19, 38, 76, 152, 29, 58, 116, 232, 253, 215, 131, 43, 86, 172, 117, 234, 249, 223,
63 147, 11, 22, 44, 88, 176, 77, 154, 25, 50, 100, 200, 189, 87, 174, 113, 226, 233, 255, 211, 139, 59,
64 118, 236, 245, 199, 163, 107, 214, 129, 47, 94, 188, 85, 170, 121, 242, 201, 191, 83, 166, 97, 194, 169,
65 127, 254, 209, 143, 51, 102, 204, 181, 71, 142, 49, 98, 196, 165, 103, 206, 177, 79, 158, 17, 34, 68,
66 136, 61, 122, 244, 197, 167, 99, 198, 161, 111, 222, 145, 15, 30, 60, 120, 240, 205, 183, 67, 134, 33,
67 66, 132, 37, 74, 148, 5, 10, 20, 40, 80, 160, 109, 218, 153, 31, 62, 124, 248, 221, 151, 3, 6,
68 12, 24, 48, 96, 192, 173, 119, 238, 241, 207, 179, 75, 150, 0};
69
70#undef CHKPASS
71#define CHKPASS \
72 { \
73 if (passFail == DmtxFail) \
74 return DmtxFail; \
75 }
83static DmtxPassFail rsEncode(DmtxMessage *message, int sizeIdx)
84{
85 int i, j;
86 int blockStride, blockIdx;
87 int blockErrorWords, symbolDataWords, symbolErrorWords, symbolTotalWords;
88 DmtxPassFail passFail;
89 DmtxByte val, *eccPtr;
92 DmtxByteList gen = dmtxByteListBuild(genStorage, sizeof(genStorage));
93 DmtxByteList ecc = dmtxByteListBuild(eccStorage, sizeof(eccStorage));
94
96 blockErrorWords = dmtxGetSymbolAttribute(DmtxSymAttribBlockErrorWords, sizeIdx);
97 symbolDataWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx);
98 symbolErrorWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolErrorWords, sizeIdx);
99 symbolTotalWords = symbolDataWords + symbolErrorWords;
100
101 /* Populate generator polynomial */
102 rsGenPoly(&gen, blockErrorWords);
103
104 /* For each interleaved block... */
105 for (blockIdx = 0; blockIdx < blockStride; blockIdx++) {
106 /* Generate error codewords */
107 dmtxByteListInit(&ecc, blockErrorWords, 0, &passFail);
108 CHKPASS;
109 for (i = blockIdx; i < symbolDataWords; i += blockStride) {
110 val = GfAdd(ecc.b[blockErrorWords - 1], message->code[i]);
111
112 for (j = blockErrorWords - 1; j > 0; j--) {
113 DMTX_CHECK_BOUNDS(&ecc, j);
114 DMTX_CHECK_BOUNDS(&ecc, j - 1);
115 DMTX_CHECK_BOUNDS(&gen, j);
116 ecc.b[j] = GfAdd(ecc.b[j - 1], GfMult(gen.b[j], val));
117 }
118
119 ecc.b[0] = GfMult(gen.b[0], val);
120 }
121
122 /* Copy to output message */
123 eccPtr = ecc.b + blockErrorWords;
124 for (i = symbolDataWords + blockIdx; i < symbolTotalWords; i += blockStride) {
125 message->code[i] = *(--eccPtr);
126 }
127
128 DmtxAssert(ecc.b == eccPtr);
129 }
130
131 return DmtxPass;
132}
133
134#undef CHKPASS
135#define CHKPASS \
136 { \
137 if (passFail == DmtxFail) \
138 return DmtxFail; \
139 }
148static DmtxPassFail rsDecode(unsigned char *code, int sizeIdx, int fix)
149{
150 int i;
151 int blockStride, blockIdx;
152 int blockDataWords, blockErrorWords, blockMaxCorrectable;
153 // int blockDataWords, blockErrorWords, blockTotalWords, blockMaxCorrectable;
154 int symbolDataWords, symbolErrorWords, symbolTotalWords;
155 DmtxBoolean error, repairable;
156 DmtxPassFail passFail;
157 unsigned char *word;
158 DmtxByte elpStorage[MAX_ERROR_WORD_COUNT];
159 DmtxByte synStorage[MAX_ERROR_WORD_COUNT + 1];
160 DmtxByte recStorage[NN];
161 DmtxByte locStorage[NN];
162 DmtxByteList elp = dmtxByteListBuild(elpStorage, sizeof(elpStorage));
163 DmtxByteList syn = dmtxByteListBuild(synStorage, sizeof(synStorage));
164 DmtxByteList rec = dmtxByteListBuild(recStorage, sizeof(recStorage));
165 DmtxByteList loc = dmtxByteListBuild(locStorage, sizeof(locStorage));
166
168 blockErrorWords = dmtxGetSymbolAttribute(DmtxSymAttribBlockErrorWords, sizeIdx);
169 blockMaxCorrectable = dmtxGetSymbolAttribute(DmtxSymAttribBlockMaxCorrectable, sizeIdx);
170 symbolDataWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, sizeIdx);
171 symbolErrorWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolErrorWords, sizeIdx);
172 symbolTotalWords = symbolDataWords + symbolErrorWords;
173
174 /* For each interleaved block */
175 for (blockIdx = 0; blockIdx < blockStride; blockIdx++) {
176 /* Data word count depends on blockIdx due to special case at 144x144 */
177 blockDataWords = dmtxGetBlockDataSize(sizeIdx, blockIdx);
178 // blockTotalWords = blockErrorWords + blockDataWords;
179
180 /* Populate received list (rec) with data and error codewords */
181 dmtxByteListInit(&rec, 0, 0, &passFail);
182 CHKPASS;
183
184 /* Start with final error word and work backward */
185 word = code + symbolTotalWords + blockIdx - blockStride;
186 for (i = 0; i < blockErrorWords; i++) {
187 dmtxByteListPush(&rec, *word, &passFail);
188 CHKPASS;
189 word -= blockStride;
190 }
191
192 /* Start with final data word and work backward */
193 word = code + blockIdx + (blockStride * (blockDataWords - 1));
194 for (i = 0; i < blockDataWords; i++) {
195 dmtxByteListPush(&rec, *word, &passFail);
196 CHKPASS;
197 word -= blockStride;
198 }
199
200 /* Compute syndromes (syn) */
201 error = rsComputeSyndromes(&syn, &rec, blockErrorWords);
202
203 /* Error(s) detected: Attempt repair */
204 if (error) {
205 /* Find error locator polynomial (elp) */
206 repairable = rsFindErrorLocatorPoly(&elp, &syn, blockErrorWords, blockMaxCorrectable);
207 if (!repairable) {
208 return DmtxFail;
209 }
210
211 /* Find error positions (loc) */
212 repairable = rsFindErrorLocations(&loc, &elp);
213 if (!repairable) {
214 return DmtxFail;
215 }
216
217 /* Find error values and repair */
218 rsRepairErrors(&rec, &loc, &elp, &syn);
219 }
220
221 /*
222 * Overwrite output with correct/corrected values
223 */
224
225 /* Start with first data word and work forward */
226 word = code + blockIdx;
227 for (i = 0; i < blockDataWords; i++) {
228 *word = dmtxByteListPop(&rec, &passFail);
229 CHKPASS;
230 word += blockStride;
231 }
232
233 /* Start with first error word and work forward */
234 word = code + symbolDataWords + blockIdx;
235 for (i = 0; i < blockErrorWords; i++) {
236 *word = dmtxByteListPop(&rec, &passFail);
237 CHKPASS;
238 word += blockStride;
239 }
240 }
241
242 return DmtxPass;
243}
244
245#undef CHKPASS
246#define CHKPASS \
247 { \
248 if (passFail == DmtxFail) \
249 return DmtxFail; \
250 }
258static DmtxPassFail rsGenPoly(DmtxByteList *gen, int errorWordCount)
259{
260 int i, j;
261 DmtxPassFail passFail;
262
263 /* Initialize all coefficients to 1 */
264 dmtxByteListInit(gen, errorWordCount, 1, &passFail);
265 CHKPASS;
266
267 /* Generate polynomial */
268 for (i = 0; i < gen->length; i++) {
269 for (j = i; j >= 0; j--) {
270 gen->b[j] = GfMultAntilog(gen->b[j], i + 1);
271 if (j > 0) {
272 gen->b[j] = GfAdd(gen->b[j], gen->b[j - 1]);
273 }
274 }
275 }
276
277 return DmtxPass;
278}
279
280/* XXX this CHKPASS isn't doing what we want ... really need a error reporting strategy */
281#undef CHKPASS
282#define CHKPASS \
283 { \
284 if (passFail == DmtxFail) \
285 return DmtxTrue; \
286 }
298static DmtxBoolean rsComputeSyndromes(DmtxByteList *syn, const DmtxByteList *rec, int blockErrorWords)
299{
300 int i, j;
301 DmtxPassFail passFail;
302 DmtxBoolean error = DmtxFalse;
303
304 /* Initialize all coefficients to 0 */
305 dmtxByteListInit(syn, blockErrorWords + 1, 0, &passFail);
306 CHKPASS;
307
308 for (i = 1; i < syn->length; i++) {
309 /* Calculate syndrome at i */
310 for (j = 0; j < rec->length; j++) { /* alternatively: j < blockTotalWords */
311 syn->b[i] = GfAdd(syn->b[i], GfMultAntilog(rec->b[j], i * j));
312 }
313
314 /* Non-zero syndrome indicates presence of error(s) */
315 if (syn->b[i] != 0) {
316 error = DmtxTrue;
317 }
318 }
319
320 return error;
321}
322
323/* XXX this CHKPASS isn't doing what we want ... really need a error reporting strategy */
324#undef CHKPASS
325#define CHKPASS \
326 { \
327 if (passFail == DmtxFail) \
328 return DmtxFalse; \
329 }
339static DmtxBoolean rsFindErrorLocatorPoly(DmtxByteList *elpOut, const DmtxByteList *syn, int errorWordCount,
340 int maxCorrectable)
341{
342 int i, iNext, j;
343 int m, mCmp, lambda;
344 DmtxByte disTmp, disStorage[MAX_ERROR_WORD_COUNT + 1];
347 DmtxPassFail passFail;
348
349 dis = dmtxByteListBuild(disStorage, sizeof(disStorage));
350 dmtxByteListInit(&dis, 0, 0, &passFail);
351 CHKPASS;
352
353 for (i = 0; i < MAX_ERROR_WORD_COUNT + 2; i++) {
354 elp[i] = dmtxByteListBuild(elpStorage[i], sizeof(elpStorage[i]));
355 dmtxByteListInit(&elp[i], 0, 0, &passFail);
356 CHKPASS;
357 }
358
359 /* iNext = 0 */
360 dmtxByteListPush(&elp[0], 1, &passFail);
361 CHKPASS;
362 dmtxByteListPush(&dis, 1, &passFail);
363 CHKPASS;
364
365 /* iNext = 1 */
366 dmtxByteListPush(&elp[1], 1, &passFail);
367 CHKPASS;
368 dmtxByteListPush(&dis, syn->b[1], &passFail);
369 CHKPASS;
370
371 for (iNext = 2, i = 1; /* explicit break */; i = iNext++) {
372 if (dis.b[i] == 0) {
373 /* Simple case: Copy directly from previous iteration */
374 dmtxByteListCopy(&elp[iNext], &elp[i], &passFail);
375 CHKPASS;
376 } else {
377 /* Find earlier iteration (m) that provides maximal (m - lambda) */
378 for (m = 0, mCmp = 1; mCmp < i; mCmp++) {
379 if (dis.b[mCmp] != 0 && (mCmp - elp[mCmp].length) >= (m - elp[m].length)) {
380 m = mCmp;
381 }
382 }
383
384 /* Calculate error location polynomial elp[i] (set 1st term) */
385 for (lambda = elp[m].length - 1, j = 0; j <= lambda; j++) {
386 elp[iNext].b[j + i - m] =
387 (elp[i - 1].b[j] == 0)
388 ? 0
389 : antilog301[(NN - log301[dis.b[m]] + log301[dis.b[i]] + log301[elp[m].b[j]]) % NN];
390 }
391
392 /* Calculate error location polynomial elp[i] (add 2nd term) */
393 for (lambda = elp[i].length - 1, j = 0; j <= lambda; j++) {
394 elp[iNext].b[j] = GfAdd(elp[iNext].b[j], elp[i].b[j]);
395 }
396
397 elp[iNext].length = max(elp[i].length, elp[m].length + i - m);
398 }
399
400 lambda = elp[iNext].length - 1;
401 if (i == errorWordCount || i >= lambda + maxCorrectable) {
402 break;
403 }
404
405 /* Calculate discrepancy dis.b[i] */
406 for (disTmp = syn->b[iNext], j = 1; j <= lambda; j++) {
407 disTmp = GfAdd(disTmp, GfMult(syn->b[iNext - j], elp[iNext].b[j]));
408 }
409
410 DmtxAssert(dis.length == iNext);
411 dmtxByteListPush(&dis, disTmp, &passFail);
412 CHKPASS;
413 }
414
415 dmtxByteListCopy(elpOut, &elp[iNext], &passFail);
416 CHKPASS;
417
418 return (lambda <= maxCorrectable) ? DmtxTrue : DmtxFalse;
419}
420
421#undef CHKPASS
422#define CHKPASS \
423 { \
424 if (passFail == DmtxFail) \
425 return DmtxFalse; \
426 }
438{
439 int i, j;
440 int lambda = elp->length - 1;
441 DmtxPassFail passFail;
442 DmtxByte q, regStorage[MAX_ERROR_WORD_COUNT];
443 DmtxByteList reg = dmtxByteListBuild(regStorage, sizeof(regStorage));
444
445 dmtxByteListCopy(&reg, elp, &passFail);
446 CHKPASS;
447 dmtxByteListInit(loc, 0, 0, &passFail);
448 CHKPASS;
449
450 for (i = 1; i <= NN; i++) {
451 for (q = 1, j = 1; j <= lambda; j++) {
452 reg.b[j] = GfMultAntilog(reg.b[j], j);
453 q = GfAdd(q, reg.b[j]);
454 }
455
456 if (q == 0) {
457 dmtxByteListPush(loc, NN - i, &passFail);
458 CHKPASS;
459 }
460 }
461
462 return (loc->length == lambda) ? DmtxTrue : DmtxFalse;
463}
464
465#undef CHKPASS
466#define CHKPASS \
467 { \
468 if (passFail == DmtxFail) \
469 return DmtxFail; \
470 }
486 const DmtxByteList *syn)
487{
488 int i, j, q;
489 int lambda = elp->length - 1;
490 DmtxPassFail passFail;
491 DmtxByte zVal, root, err;
492 DmtxByte zStorage[MAX_ERROR_WORD_COUNT + 1];
493 DmtxByteList z = dmtxByteListBuild(zStorage, sizeof(zStorage));
494
495 /* Form polynomial z(x) */
496 dmtxByteListPush(&z, 1, &passFail);
497 CHKPASS;
498 for (i = 1; i <= lambda; i++) {
499 for (zVal = GfAdd(syn->b[i], elp->b[i]), j = 1; j < i; j++) {
500 zVal = GfAdd(zVal, GfMult(elp->b[i - j], syn->b[j]));
501 }
502 dmtxByteListPush(&z, zVal, &passFail);
503 CHKPASS;
504 }
505
506 for (i = 0; i < lambda; i++) {
507 /* Calculate numerator of error term */
508 root = NN - loc->b[i];
509
510 for (err = 1, j = 1; j <= lambda; j++) {
511 err = GfAdd(err, GfMultAntilog(z.b[j], j * root));
512 }
513
514 if (err == 0) {
515 continue;
516 }
517
518 /* Calculate denominator of error term */
519 for (q = 0, j = 0; j < lambda; j++) {
520 if (j != i) {
521 q += log301[1 ^ antilog301[(loc->b[j] + root) % NN]];
522 }
523 }
524 q %= NN;
525
526 err = GfMultAntilog(err, NN - q);
527 rec->b[loc->b[i]] = GfAdd(rec->b[loc->b[i]], err);
528 }
529
530 return DmtxPass;
531}
libdmtx - Data Matrix Encoding/Decoding Library Copyright 2008, 2009 Mike Laughton.
#define DmtxPassFail
Definition dmtx.h:42
int dmtxGetSymbolAttribute(int attribute, int sizeIdx)
根据规格索引返回二维码规格各个参数
Definition dmtxsymbol.c:45
#define DmtxTrue
Definition dmtx.h:47
DmtxByteList dmtxByteListBuild(DmtxByte *storage, int capacity)
void dmtxByteListPush(DmtxByteList *list, DmtxByte value, DmtxPassFail *passFail)
int dmtxGetBlockDataSize(int sizeIdx, int blockIdx)
Retrieve data size for a specific symbol size and block number.
Definition dmtxsymbol.c:118
@ DmtxSymAttribBlockMaxCorrectable
Definition dmtx.h:164
@ DmtxSymAttribBlockErrorWords
Definition dmtx.h:163
@ DmtxSymAttribSymbolErrorWords
Definition dmtx.h:166
@ DmtxSymAttribSymbolDataWords
Definition dmtx.h:165
@ DmtxSymAttribInterleavedBlocks
Definition dmtx.h:162
#define DmtxBoolean
Definition dmtx.h:46
#define DmtxPass
Definition dmtx.h:43
DmtxByte dmtxByteListPop(DmtxByteList *list, DmtxPassFail *passFail)
void dmtxByteListCopy(DmtxByteList *dst, const DmtxByteList *src, DmtxPassFail *passFail)
#define DmtxFalse
Definition dmtx.h:48
unsigned char DmtxByte
Definition dmtx.h:293
#define DmtxFail
Definition dmtx.h:44
void dmtxByteListInit(DmtxByteList *list, int length, DmtxByte value, DmtxPassFail *passFail)
#define DMTX_CHECK_BOUNDS(l, i)
Definition dmtxreedsol.c:29
static DmtxPassFail rsDecode(unsigned char *code, int sizeIdx, int fix)
Decode xyz.
#define NN
Definition dmtxreedsol.c:26
#define GfMult(a, b)
Definition dmtxreedsol.c:35
#define MAX_ERROR_WORD_COUNT
Definition dmtxreedsol.c:27
static DmtxPassFail rsRepairErrors(DmtxByteList *rec, const DmtxByteList *loc, const DmtxByteList *elp, const DmtxByteList *syn)
Find the error values and repair.
static DmtxByte antilog301[]
Definition dmtxreedsol.c:56
static DmtxBoolean rsComputeSyndromes(DmtxByteList *syn, const DmtxByteList *rec, int blockErrorWords)
Populate generator polynomial.
#define GfAdd(a, b)
Definition dmtxreedsol.c:32
static DmtxBoolean rsFindErrorLocations(DmtxByteList *loc, const DmtxByteList *elp)
Find roots of the error locator polynomial (Chien Search).
static DmtxBoolean rsFindErrorLocatorPoly(DmtxByteList *elpOut, const DmtxByteList *syn, int errorWordCount, int maxCorrectable)
Find the error location polynomial using Berlekamp-Massey.
#define CHKPASS
Definition dmtxreedsol.c:71
static DmtxPassFail rsGenPoly(DmtxByteList *gen, int errorWordCount)
Populate generator polynomial.
#define GfMultAntilog(a, b)
Definition dmtxreedsol.c:38
static DmtxByte log301[]
Definition dmtxreedsol.c:41
static DmtxPassFail rsEncode(DmtxMessage *message, int sizeIdx)
Encode xyz.
Definition dmtxreedsol.c:83
libdmtx - Data Matrix Encoding/Decoding Library Copyright 2008, 2009 Mike Laughton.
#define DmtxAssert(expr)
Definition dmtxstatic.h:96
#define max(X, Y)
Definition dmtxstatic.h:65
DmtxByteList Use signed int for length fields instead of size_t to play nicely with RS arithmetic.
DataMatrix编码内容
Definition dmtx.h:421
unsigned char * code
指向码字(数据字和纠错字)的指针
Definition dmtx.h:429