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
dmtxdecodescheme.c
Go to the documentation of this file.
1
16#include <assert.h>
17#include <limits.h>
18#include <math.h>
19
20#include "dmtx.h"
21#include "dmtxstatic.h"
22
30extern DmtxPassFail decodeDataStream(DmtxMessage *msg, int sizeIdx, unsigned char *outputStart)
31{
32 // /* 绘制DataMatrix数据区矩阵 */
33 // dmtxLogDebug("libdmtx::decodeDataStream()");
34 // int oned = (int)sqrt((double)msg->arraySize);
35 // for (int i = 0; i < msg->arraySize; i++) {
36 // printf(" %c.", msg->array[i]);
37 // if (i % oned == oned - 1) {
38 // printf("\n");
39 // }
40 // }
41
42 DmtxBoolean macro = DmtxFalse;
43 DmtxScheme encScheme;
44 unsigned char *ptr, *dataEnd;
45
46 msg->output = (outputStart == NULL) ? msg->output : outputStart;
47 msg->outputIdx = 0;
48
49 ptr = msg->code;
51
52 /* Print macro header if first codeword triggers it */
53 if (*ptr == DmtxValue05Macro || *ptr == DmtxValue06Macro) {
54 pushOutputMacroHeader(msg, *ptr);
55 macro = DmtxTrue;
56 }
57
58 while (ptr < dataEnd) {
59 encScheme = getEncodationScheme(*ptr);
60 if (encScheme != DmtxSchemeAscii) {
61 ptr++;
62 }
63
64 switch (encScheme) {
65 case DmtxSchemeAscii:
66 ptr = decodeSchemeAscii(msg, ptr, dataEnd);
67 break;
68 case DmtxSchemeC40:
69 case DmtxSchemeText:
70 ptr = decodeSchemeC40Text(msg, ptr, dataEnd, encScheme);
71 break;
72 case DmtxSchemeX12:
73 ptr = decodeSchemeX12(msg, ptr, dataEnd);
74 break;
76 ptr = decodeSchemeEdifact(msg, ptr, dataEnd);
77 break;
79 ptr = decodeSchemeBase256(msg, ptr, dataEnd);
80 break;
81 default:
82 /* error */
83 break;
84 }
85
86 if (ptr == NULL) {
87 return DmtxFail;
88 }
89 }
90
91 /* Print macro trailer if required */
92 if (macro == DmtxTrue) {
94 }
95
96 return DmtxPass;
97}
98
104static int getEncodationScheme(unsigned char cw)
105{
106 DmtxScheme encScheme;
107
108 switch (cw) {
110 encScheme = DmtxSchemeC40;
111 break;
113 encScheme = DmtxSchemeText;
114 break;
116 encScheme = DmtxSchemeX12;
117 break;
119 encScheme = DmtxSchemeEdifact;
120 break;
122 encScheme = DmtxSchemeBase256;
123 break;
124 default:
125 encScheme = DmtxSchemeAscii;
126 break;
127 }
128
129 return encScheme;
130}
131
136static void pushOutputWord(DmtxMessage *msg, int value)
137{
138 DmtxAssert(value >= 0 && value < 256);
139
140 msg->output[msg->outputIdx++] = (unsigned char)value;
141}
142
148{
149 return (value >= 0 && value < 256) ? DmtxTrue : DmtxFalse;
150}
151
156static void pushOutputC40TextWord(DmtxMessage *msg, C40TextState *state, int value)
157{
158 DmtxAssert(value >= 0 && value < 256);
159
160 msg->output[msg->outputIdx] = (unsigned char)value;
161
162 if (state->upperShift == DmtxTrue) {
163 DmtxAssert(value < 128);
164 msg->output[msg->outputIdx] += 128;
165 }
166
167 msg->outputIdx++;
168
169 state->shift = DmtxC40TextBasicSet;
170 state->upperShift = DmtxFalse;
171}
172
177static void pushOutputMacroHeader(DmtxMessage *msg, int macroType)
178{
179 pushOutputWord(msg, '[');
180 pushOutputWord(msg, ')');
181 pushOutputWord(msg, '>');
182 pushOutputWord(msg, 30); /* ASCII RS */
183 pushOutputWord(msg, '0');
184
185 DmtxAssert(macroType == DmtxValue05Macro || macroType == DmtxValue06Macro);
186 if (macroType == DmtxValue05Macro) {
187 pushOutputWord(msg, '5');
188 } else {
189 pushOutputWord(msg, '6');
190 }
191
192 pushOutputWord(msg, 29); /* ASCII GS */
193}
194
200{
201 pushOutputWord(msg, 30); /* ASCII RS */
202 pushOutputWord(msg, 4); /* ASCII EOT */
203}
204
213static unsigned char *decodeSchemeAscii(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd)
214{
215 int upperShift = DmtxFalse;
216
217 while (ptr < dataEnd) {
218 int codeword = (int)(*ptr);
219
221 return ptr;
222 }
223 ptr++;
224
225 if (upperShift == DmtxTrue) {
226 int pushword = codeword + 127;
227 if (validOutputWord(pushword) != DmtxTrue) {
228 return NULL;
229 }
230 pushOutputWord(msg, pushword);
231 upperShift = DmtxFalse;
232 } else if (codeword == DmtxValueAsciiUpperShift) {
233 upperShift = DmtxTrue;
234 } else if (codeword == DmtxValueAsciiPad) {
235 DmtxAssert(dataEnd >= ptr);
236 DmtxAssert(dataEnd - ptr <= INT_MAX);
237 msg->padCount = (int)(dataEnd - ptr);
238 return dataEnd;
239 } else if (codeword == 0 || codeword >= 242) {
240 return ptr;
241 } else if (codeword <= 128) {
242 pushOutputWord(msg, codeword - 1);
243 } else if (codeword <= 229) {
244 int digits = codeword - 130;
245 pushOutputWord(msg, digits / 10 + '0');
246 pushOutputWord(msg, digits - (digits / 10) * 10 + '0');
247 } else if (codeword == DmtxValueFNC1) {
248 if (msg->fnc1 != DmtxUndefined) {
249 int pushword = msg->fnc1;
250 if (validOutputWord(pushword) != DmtxTrue) {
251 return NULL;
252 }
253 pushOutputWord(msg, pushword);
254 }
255 }
256 }
257
258 return ptr;
259}
260
269static unsigned char *decodeSchemeC40Text(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd,
270 DmtxScheme encScheme)
271{
272 int i;
273 int packed;
274 int c40Values[3];
275 C40TextState state;
276
278 state.upperShift = DmtxFalse;
279
280 DmtxAssert(encScheme == DmtxSchemeC40 || encScheme == DmtxSchemeText);
281
282 /* Unlatch is implied if only one codeword remains */
283 if (dataEnd - ptr < 2) {
284 return ptr;
285 }
286
287 while (ptr < dataEnd) {
288 /* FIXME Also check that ptr+1 is safe to access */
289 packed = (*ptr << 8) | *(ptr + 1);
290 c40Values[0] = ((packed - 1) / 1600);
291 c40Values[1] = ((packed - 1) / 40) % 40;
292 c40Values[2] = (packed - 1) % 40;
293 ptr += 2;
294
295 for (i = 0; i < 3; i++) {
296 if (state.shift == DmtxC40TextBasicSet) { /* Basic set */
297 if (c40Values[i] <= 2) {
298 state.shift = c40Values[i] + 1;
299 } else if (c40Values[i] == 3) {
300 pushOutputC40TextWord(msg, &state, ' ');
301 } else if (c40Values[i] <= 13) {
302 pushOutputC40TextWord(msg, &state, c40Values[i] - 13 + '9'); /* 0-9 */
303 } else if (c40Values[i] <= 39) {
304 if (encScheme == DmtxSchemeC40) {
305 pushOutputC40TextWord(msg, &state, c40Values[i] - 39 + 'Z'); /* A-Z */
306 } else if (encScheme == DmtxSchemeText) {
307 pushOutputC40TextWord(msg, &state, c40Values[i] - 39 + 'z'); /* a-z */
308 }
309 }
310 } else if (state.shift == DmtxC40TextShift1) { /* Shift 1 set */
311 pushOutputC40TextWord(msg, &state, c40Values[i]); /* ASCII 0 - 31 */
312 } else if (state.shift == DmtxC40TextShift2) { /* Shift 2 set */
313 if (c40Values[i] <= 14) {
314 pushOutputC40TextWord(msg, &state, c40Values[i] + 33); /* ASCII 33 - 47 */
315 } else if (c40Values[i] <= 21) {
316 pushOutputC40TextWord(msg, &state, c40Values[i] + 43); /* ASCII 58 - 64 */
317 } else if (c40Values[i] <= 26) {
318 pushOutputC40TextWord(msg, &state, c40Values[i] + 69); /* ASCII 91 - 95 */
319 } else if (c40Values[i] == 27) {
320 if (msg->fnc1 != DmtxUndefined) {
321 pushOutputC40TextWord(msg, &state, msg->fnc1);
322 }
323 } else if (c40Values[i] == 30) {
324 state.upperShift = DmtxTrue;
326 }
327 } else if (state.shift == DmtxC40TextShift3) { /* Shift 3 set */
328 if (encScheme == DmtxSchemeC40) {
329 pushOutputC40TextWord(msg, &state, c40Values[i] + 96);
330 } else if (encScheme == DmtxSchemeText) {
331 if (c40Values[i] == 0) {
332 pushOutputC40TextWord(msg, &state, c40Values[i] + 96);
333 } else if (c40Values[i] <= 26) {
334 pushOutputC40TextWord(msg, &state, c40Values[i] - 26 + 'Z'); /* A-Z */
335 } else {
336 pushOutputC40TextWord(msg, &state, c40Values[i] - 31 + 127); /* { | } ~ DEL */
337 }
338 }
339 }
340 }
341
342 /* Unlatch if codeword 254 follows 2 codewords in C40/Text encodation */
343 if (*ptr == DmtxValueCTXUnlatch) {
344 return ptr + 1;
345 }
346
347 /* Unlatch is implied if only one codeword remains */
348 if (dataEnd - ptr < 2) {
349 return ptr;
350 }
351 }
352
353 return ptr;
354}
355
363static unsigned char *decodeSchemeX12(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd)
364{
365 int i;
366 int packed;
367 int x12Values[3];
368
369 /* Unlatch is implied if only one codeword remains */
370 if (dataEnd - ptr < 2) {
371 return ptr;
372 }
373
374 while (ptr < dataEnd) {
375 /* FIXME Also check that ptr+1 is safe to access */
376 packed = (*ptr << 8) | *(ptr + 1);
377 x12Values[0] = ((packed - 1) / 1600);
378 x12Values[1] = ((packed - 1) / 40) % 40;
379 x12Values[2] = (packed - 1) % 40;
380 ptr += 2;
381
382 for (i = 0; i < 3; i++) {
383 if (x12Values[i] == 0) {
384 pushOutputWord(msg, 13);
385 } else if (x12Values[i] == 1) {
386 pushOutputWord(msg, 42);
387 } else if (x12Values[i] == 2) {
388 pushOutputWord(msg, 62);
389 } else if (x12Values[i] == 3) {
390 pushOutputWord(msg, 32);
391 } else if (x12Values[i] <= 13) {
392 pushOutputWord(msg, x12Values[i] + 44);
393 } else if (x12Values[i] <= 90) {
394 pushOutputWord(msg, x12Values[i] + 51);
395 }
396 }
397
398 /* Unlatch if codeword 254 follows 2 codewords in C40/Text encodation */
399 if (*ptr == DmtxValueCTXUnlatch) {
400 return ptr + 1;
401 }
402
403 /* Unlatch is implied if only one codeword remains */
404 if (dataEnd - ptr < 2) {
405 return ptr;
406 }
407 }
408
409 return ptr;
410}
411
419static unsigned char *decodeSchemeEdifact(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd)
420{
421 int i;
422 unsigned char unpacked[4];
423
424 /* Unlatch is implied if fewer than 3 codewords remain */
425 if (dataEnd - ptr < 3) {
426 return ptr;
427 }
428
429 while (ptr < dataEnd) {
430 /* FIXME Also check that ptr+2 is safe to access -- shouldn't be a
431 problem because I'm guessing you can guarantee there will always
432 be at least 3 error codewords */
433 unpacked[0] = (*ptr & 0xfc) >> 2;
434 unpacked[1] = (*ptr & 0x03) << 4 | (*(ptr + 1) & 0xf0) >> 4;
435 unpacked[2] = (*(ptr + 1) & 0x0f) << 2 | (*(ptr + 2) & 0xc0) >> 6;
436 unpacked[3] = *(ptr + 2) & 0x3f;
437
438 for (i = 0; i < 4; i++) {
439 /* Advance input ptr (4th value comes from already-read 3rd byte) */
440 if (i < 3) {
441 ptr++;
442 }
443
444 /* Test for unlatch condition */
445 if (unpacked[i] == DmtxValueEdifactUnlatch) {
446 DmtxAssert(msg->output[msg->outputIdx] == 0); /* XXX dirty why? */
447 return ptr;
448 }
449
450 pushOutputWord(msg, unpacked[i] ^ (((unpacked[i] & 0x20) ^ 0x20) << 1));
451 }
452
453 /* Unlatch is implied if fewer than 3 codewords remain */
454 if (dataEnd - ptr < 3) {
455 return ptr;
456 }
457 }
458
459 return ptr;
460
461 /* XXX the following version should be safer, but requires testing before replacing the old version
462 int bits = 0;
463 int bitCount = 0;
464 int value;
465
466 while(ptr < dataEnd) {
467
468 if(bitCount < 6) {
469 bits = (bits << 8) | *(ptr++);
470 bitCount += 8;
471 }
472
473 value = bits >> (bitCount - 6);
474 bits -= (value << (bitCount - 6));
475 bitCount -= 6;
476
477 if(value == 0x1f) {
478 DmtxAssert(bits == 0); // should be padded with zero-value bits
479 return ptr;
480 }
481 pushOutputWord(msg, value ^ (((value & 0x20) ^ 0x20) << 1));
482
483 // Unlatch implied if just completed triplet and 1 or 2 words are left
484 if(bitCount == 0 && dataEnd - ptr - 1 > 0 && dataEnd - ptr - 1 < 3)
485 return ptr;
486 }
487
488 DmtxAssert(bits == 0); // should be padded with zero-value bits
489 DmtxAssert(bitCount == 0); // should be padded with zero-value bits
490 return ptr;
491 */
492}
493
502static unsigned char *decodeSchemeBase256(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd)
503{
504 int d0, d1;
505 int idx;
506 unsigned char *ptrEnd;
507
508 /* Find positional index used for unrandomizing */
509 DmtxAssert(ptr + 1 >= msg->code);
510 DmtxAssert(ptr + 1 - msg->code <= INT_MAX);
511 idx = (int)(ptr + 1 - msg->code);
512
513 d0 = unRandomize255State(*(ptr++), idx++);
514 if (d0 == 0) {
515 ptrEnd = dataEnd;
516 } else if (d0 <= 249) {
517 ptrEnd = ptr + d0;
518 } else {
519 d1 = unRandomize255State(*(ptr++), idx++);
520 ptrEnd = ptr + (d0 - 249) * 250 + d1;
521 }
522
523 if (ptrEnd > dataEnd) {
524 return NULL;
525 }
526
527 while (ptr < ptrEnd) {
528 pushOutputWord(msg, unRandomize255State(*(ptr++), idx++));
529 }
530
531 return ptr;
532}
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
@ DmtxSymAttribSymbolDataWords
Definition dmtx.h:165
#define DmtxBoolean
Definition dmtx.h:46
#define DmtxPass
Definition dmtx.h:43
enum DmtxScheme_enum DmtxScheme
#define DmtxUndefined
Definition dmtx.h:40
@ DmtxSchemeText
Definition dmtx.h:92
@ DmtxSchemeC40
Definition dmtx.h:91
@ DmtxSchemeBase256
Definition dmtx.h:95
@ DmtxSchemeEdifact
Definition dmtx.h:94
@ DmtxSchemeX12
Definition dmtx.h:93
@ DmtxSchemeAscii
Definition dmtx.h:90
#define DmtxFalse
Definition dmtx.h:48
#define DmtxFail
Definition dmtx.h:44
static unsigned char * decodeSchemeC40Text(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd, DmtxScheme encScheme)
Decode stream assuming C40 or Text encodation.
static unsigned char * decodeSchemeAscii(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd)
Decode stream assuming standard ASCII encodation.
static int getEncodationScheme(unsigned char cw)
Determine next encodation scheme.
static unsigned char * decodeSchemeX12(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd)
Decode stream assuming X12 encodation.
static void pushOutputWord(DmtxMessage *msg, int value)
static DmtxBoolean validOutputWord(int value)
static void pushOutputMacroHeader(DmtxMessage *msg, int macroType)
static unsigned char * decodeSchemeEdifact(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd)
Decode stream assuming EDIFACT encodation.
DmtxPassFail decodeDataStream(DmtxMessage *msg, int sizeIdx, unsigned char *outputStart)
Translate encoded data stream into final output.
static void pushOutputMacroTrailer(DmtxMessage *msg)
static unsigned char * decodeSchemeBase256(DmtxMessage *msg, unsigned char *ptr, unsigned char *dataEnd)
Decode stream assuming Base 256 encodation.
static void pushOutputC40TextWord(DmtxMessage *msg, C40TextState *state, int value)
libdmtx - Data Matrix Encoding/Decoding Library Copyright 2008, 2009 Mike Laughton.
#define DmtxValueBase256Latch
Definition dmtxstatic.h:32
#define DmtxValueAsciiPad
Definition dmtxstatic.h:37
#define DmtxValue05Macro
Definition dmtxstatic.h:45
#define DmtxC40TextShift2
Definition dmtxstatic.h:51
#define DmtxValueC40Latch
Definition dmtxstatic.h:28
#define DmtxAssert(expr)
Definition dmtxstatic.h:96
#define DmtxC40TextShift3
Definition dmtxstatic.h:52
#define DmtxC40TextBasicSet
Definition dmtxstatic.h:49
#define DmtxValueTextLatch
Definition dmtxstatic.h:29
static unsigned char unRandomize255State(unsigned char value, int idx)
#define DmtxValue06Macro
Definition dmtxstatic.h:46
#define DmtxValueX12Latch
Definition dmtxstatic.h:30
#define DmtxValueFNC1
Definition dmtxstatic.h:42
#define DmtxValueAsciiUpperShift
Definition dmtxstatic.h:38
#define DmtxValueEdifactUnlatch
Definition dmtxstatic.h:35
#define DmtxC40TextShift1
Definition dmtxstatic.h:50
#define DmtxValueCTXUnlatch
Definition dmtxstatic.h:34
#define DmtxValueEdifactLatch
Definition dmtxstatic.h:31
DmtxBoolean upperShift
Definition dmtxstatic.h:175
DataMatrix编码内容
Definition dmtx.h:421
unsigned char * code
指向码字(数据字和纠错字)的指针
Definition dmtx.h:429
int outputIdx
Internal index used to store output progress.
Definition dmtx.h:425
int fnc1
表示FNC1或DmtxUndefined的字符
Definition dmtx.h:427
unsigned char * output
指向二维码码值的指针
Definition dmtx.h:430