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
dmtxdecode.c
Go to the documentation of this file.
1
19#include <assert.h>
20#include <math.h>
21#include <stdio.h> // for snprintf
22#include <stdlib.h>
23#include <string.h>
24
25#include "dmtx.h"
26#include "dmtxstatic.h"
27
32extern DmtxDecode *dmtxDecodeCreate(DmtxImage *img, int scale)
33{
34 DmtxDecode *dec;
35 int width, height;
36
37 dec = (DmtxDecode *)calloc(1, sizeof(DmtxDecode));
38 if (dec == NULL) {
39 return NULL;
40 }
41
42 width = dmtxImageGetProp(img, DmtxPropWidth) / scale;
43 height = dmtxImageGetProp(img, DmtxPropHeight) / scale;
44
45 dec->fnc1 = DmtxUndefined;
46
47 dec->edgeMin = DmtxUndefined;
48 dec->edgeMax = DmtxUndefined;
49 dec->scanGap = 1;
50 dec->squareDevn = cos(50 * (M_PI / 180));
51 dec->sizeIdxExpected = DmtxSymbolShapeAuto;
52 dec->edgeThresh = 10;
53
54 dec->xMin = 0;
55 dec->xMax = width - 1;
56 dec->yMin = 0;
57 dec->yMax = height - 1;
58 dec->scale = scale;
59
60 dec->cache = (unsigned char *)calloc((size_t)width * height, sizeof(unsigned char));
61 if (dec->cache == NULL) {
62 free(dec);
63 return NULL;
64 }
65
66 dec->image = img;
67 dec->grid = initScanGrid(dec);
68
69 return dec;
70}
71
78{
79 if (dec == NULL || *dec == NULL) {
80 return DmtxFail;
81 }
82
83 if ((*dec)->cache != NULL) {
84 free((*dec)->cache);
85 }
86
87 free(*dec);
88
89 *dec = NULL;
90
91 return DmtxPass;
92}
93
101extern DmtxPassFail dmtxDecodeSetProp(DmtxDecode *dec, int prop, int value)
102{
103 switch (prop) {
104 case DmtxPropEdgeMin:
105 dec->edgeMin = value;
106 break;
107 case DmtxPropEdgeMax:
108 dec->edgeMax = value;
109 break;
110 case DmtxPropScanGap:
111 dec->scanGap = value; /* XXX Should this be scaled? */
112 break;
113 case DmtxPropFnc1:
114 dec->fnc1 = value;
115 break;
117 dec->squareDevn = cos(value * (M_PI / 180.0));
118 break;
120 dec->sizeIdxExpected = value;
121 break;
123 dec->edgeThresh = value;
124 break;
125 /* Min and Max values arrive unscaled */
126 case DmtxPropXmin:
127 dec->xMin = value / dec->scale;
128 break;
129 case DmtxPropXmax:
130 dec->xMax = value / dec->scale;
131 break;
132 case DmtxPropYmin:
133 dec->yMin = value / dec->scale;
134 break;
135 case DmtxPropYmax:
136 dec->yMax = value / dec->scale;
137 break;
138 default:
139 break;
140 }
141
142 if (dec->squareDevn <= 0.0 || dec->squareDevn >= 1.0) {
143 return DmtxFail;
144 }
145
146 if (dec->scanGap < 1) {
147 return DmtxFail;
148 }
149
150 if (dec->edgeThresh < 1 || dec->edgeThresh > 100) {
151 return DmtxFail;
152 }
153
154 /* Reinitialize scangrid in case any inputs changed */
155 dec->grid = initScanGrid(dec);
156
157 return DmtxPass;
158}
159
166extern int dmtxDecodeGetProp(DmtxDecode *dec, int prop)
167{
168 switch (prop) {
169 case DmtxPropEdgeMin:
170 return dec->edgeMin;
171 case DmtxPropEdgeMax:
172 return dec->edgeMax;
173 case DmtxPropScanGap:
174 return dec->scanGap;
175 case DmtxPropFnc1:
176 return dec->fnc1;
178 return (int)(acos(dec->squareDevn) * 180.0 / M_PI);
180 return dec->sizeIdxExpected;
182 return dec->edgeThresh;
183 case DmtxPropXmin:
184 return dec->xMin;
185 case DmtxPropXmax:
186 return dec->xMax;
187 case DmtxPropYmin:
188 return dec->yMin;
189 case DmtxPropYmax:
190 return dec->yMax;
191 case DmtxPropScale:
192 return dec->scale;
193 case DmtxPropWidth:
194 return dmtxImageGetProp(dec->image, DmtxPropWidth) / dec->scale;
195 case DmtxPropHeight:
196 return dmtxImageGetProp(dec->image, DmtxPropHeight) / dec->scale;
197 default:
198 break;
199 }
200
201 return DmtxUndefined;
202}
203
211extern unsigned char *dmtxDecodeGetCache(DmtxDecode *dec, int x, int y)
212{
213 int width, height;
214
215 DmtxAssert(dec != NULL);
216
217 /* if(dec.cacheComplete == DmtxFalse)
218 CacheImage(); */
219
220 width = dmtxDecodeGetProp(dec, DmtxPropWidth);
221 height = dmtxDecodeGetProp(dec, DmtxPropHeight);
222
223 if (x < 0 || x >= width || y < 0 || y >= height) {
224 return NULL;
225 }
226
227 return &(dec->cache[y * width + x]);
228}
229
233extern DmtxPassFail dmtxDecodeGetPixelValue(DmtxDecode *dec, int x, int y, int channel, OUT int *value)
234{
235 int xUnscaled, yUnscaled;
236 DmtxPassFail err;
237
238 xUnscaled = x * dec->scale;
239 yUnscaled = y * dec->scale;
240
241 /* Remove spherical lens distortion */
242 /* int width, height;
243 double radiusPow2, radiusPow4;
244 double factor;
245 DmtxVector2 pointShifted;
246 DmtxVector2 correctedPoint;
247
248 width = dmtxImageGetProp(img, DmtxPropWidth);
249 height = dmtxImageGetProp(img, DmtxPropHeight);
250
251 pointShifted.X = point.X - width/2.0;
252 pointShifted.Y = point.Y - height/2.0;
253
254 radiusPow2 = pointShifted.X * pointShifted.X + pointShifted.Y * pointShifted.Y;
255 radiusPow4 = radiusPow2 * radiusPow2;
256
257 factor = 1 + (k1 * radiusPow2) + (k2 * radiusPow4);
258
259 correctedPoint.X = pointShifted.X * factor + width/2.0;
260 correctedPoint.Y = pointShifted.Y * factor + height/2.0;
261
262 return correctedPoint; */
263
264 err = dmtxImageGetPixelValue(dec->image, xUnscaled, yUnscaled, channel, value);
265
266 return err;
267}
268
273{
274 DmtxBresLine lines[4];
275 DmtxPixelLoc pEmpty = {0, 0};
276 unsigned char *cache;
277 int *scanlineMin, *scanlineMax;
278 int minY, maxY, sizeY, posY, posX;
279 int i, idx;
280
281 lines[0] = bresLineInit(p0, p1, pEmpty);
282 lines[1] = bresLineInit(p1, p2, pEmpty);
283 lines[2] = bresLineInit(p2, p3, pEmpty);
284 lines[3] = bresLineInit(p3, p0, pEmpty);
285
286 minY = dec->yMax;
287 maxY = 0;
288
289 minY = min(minY, p0.y);
290 maxY = max(maxY, p0.y);
291 minY = min(minY, p1.y);
292 maxY = max(maxY, p1.y);
293 minY = min(minY, p2.y);
294 maxY = max(maxY, p2.y);
295 minY = min(minY, p3.y);
296 maxY = max(maxY, p3.y);
297
298 sizeY = maxY - minY + 1;
299
300 scanlineMin = (int *)malloc(sizeY * sizeof(int));
301 scanlineMax = (int *)calloc(sizeY, sizeof(int));
302
303 DmtxAssert(scanlineMin); /* XXX handle this better */
304 DmtxAssert(scanlineMax); /* XXX handle this better */
305
306 for (i = 0; i < sizeY; i++) {
307 scanlineMin[i] = dec->xMax;
308 }
309
310 for (i = 0; i < 4; i++) {
311 while (lines[i].loc.x != lines[i].loc1.x || lines[i].loc.y != lines[i].loc1.y) {
312 idx = lines[i].loc.y - minY;
313 scanlineMin[idx] = min(scanlineMin[idx], lines[i].loc.x);
314 scanlineMax[idx] = max(scanlineMax[idx], lines[i].loc.x);
315 bresLineStep(lines + i, 1, 0);
316 }
317 }
318
319 for (posY = minY; posY < maxY && posY < dec->yMax; posY++) {
320 idx = posY - minY;
321 for (posX = scanlineMin[idx]; posX < scanlineMax[idx] && posX < dec->xMax; posX++) {
322 cache = dmtxDecodeGetCache(dec, posX, posY);
323 if (cache != NULL) {
324 *cache |= 0x80;
325 }
326 }
327 }
328
329 free(scanlineMin);
330 free(scanlineMax);
331}
332
336extern DmtxMessage *dmtxDecodeMatrixRegion(DmtxDecode *dec, DmtxRegion *reg, int fix /*DmtxUndefined*/)
337{
338 // dmtxLogDebug("libdmtx::dmtxDecodeMatrixRegion()");
339 DmtxMessage *msg;
340
342 if (msg == NULL) {
343 return NULL;
344 }
345
346 if (populateArrayFromMatrix(dec, reg, msg) != DmtxPass) {
347 dmtxMessageDestroy(&msg);
348 return NULL;
349 }
350
351 msg->fnc1 = dec->fnc1;
352
353 {
354 DmtxVector2 topLeft, topRight, bottomLeft, bottomRight;
355 DmtxPixelLoc pxTopLeft, pxTopRight, pxBottomLeft, pxBottomRight;
356
357 topLeft.x = bottomLeft.x = topLeft.y = topRight.y = -0.1;
358 topRight.x = bottomRight.x = bottomLeft.y = bottomRight.y = 1.1;
359
360 dmtxMatrix3VMultiplyBy(&topLeft, reg->fit2raw);
361 dmtxMatrix3VMultiplyBy(&topRight, reg->fit2raw);
362 dmtxMatrix3VMultiplyBy(&bottomLeft, reg->fit2raw);
363 dmtxMatrix3VMultiplyBy(&bottomRight, reg->fit2raw);
364
365 pxTopLeft.x = (int)(0.5 + topLeft.x);
366 pxTopLeft.y = (int)(0.5 + topLeft.y);
367 pxBottomLeft.x = (int)(0.5 + bottomLeft.x);
368 pxBottomLeft.y = (int)(0.5 + bottomLeft.y);
369 pxTopRight.x = (int)(0.5 + topRight.x);
370 pxTopRight.y = (int)(0.5 + topRight.y);
371 pxBottomRight.x = (int)(0.5 + bottomRight.x);
372 pxBottomRight.y = (int)(0.5 + bottomRight.y);
373
374 cacheFillQuad(dec, pxTopLeft, pxTopRight, pxBottomRight, pxBottomLeft);
375 }
376
377 return dmtxDecodePopulatedArray(reg->sizeIdx, msg, fix);
378}
379
390DmtxMessage *dmtxDecodePopulatedArray(int sizeIdx, INOUT DmtxMessage *msg, int fix /*DmtxUndefined*/)
391{
392 /*
393 * Example msg->array indices for a 12x12 datamatrix.
394 * also, the 'L' color (usually black) is defined as 'DmtxModuleOnRGB'
395 *
396 * XX XX XX XX XX XX
397 * XX 00 01 02 03 04 05 06 07 08 09 XX
398 * XX 10 11 12 13 14 15 16 17 18 19
399 * XX 20 21 22 23 24 25 26 27 28 29 XX
400 * XX 30 31 32 33 34 35 36 37 38 39
401 * XX 40 41 42 43 44 45 46 47 48 49 XX
402 * XX 50 51 52 53 54 55 56 57 58 59
403 * XX 60 61 62 63 64 65 66 67 68 69 XX
404 * XX 70 71 72 73 74 75 76 77 78 79
405 * XX 80 81 82 83 84 85 86 87 88 89 XX
406 * XX 90 91 92 93 94 95 96 97 98 99
407 * XX XX XX XX XX XX XX XX XX XX XX XX
408 *
409 */
410
411 /* 根据bit数组(array)拼接为code */
412 modulePlacementEcc200(msg->array, msg->code, sizeIdx, DmtxModuleOnRed | DmtxModuleOnGreen | DmtxModuleOnBlue);
413
414 if (rsDecode(msg->code, sizeIdx, fix) == DmtxFail) {
415 dmtxMessageDestroy(&msg);
416 msg = NULL;
417 return NULL;
418 }
419
420 if (decodeDataStream(msg, sizeIdx, NULL) == DmtxFail) {
421 dmtxMessageDestroy(&msg);
422 msg = NULL;
423 return NULL;
424 }
425
426 return msg;
427}
428
437{
438 int offset;
439 int colorPlane;
440 DmtxMessage *oMsg, *rMsg, *gMsg, *bMsg;
441
442 colorPlane = reg->flowBegin.plane;
443
457 reg->flowBegin.plane = 0; /* kind of a hack */
458 rMsg = dmtxDecodeMatrixRegion(dec, reg, fix);
459
460 reg->flowBegin.plane = 1; /* kind of a hack */
461 gMsg = dmtxDecodeMatrixRegion(dec, reg, fix);
462
463 reg->flowBegin.plane = 2; /* kind of a hack */
464 bMsg = dmtxDecodeMatrixRegion(dec, reg, fix);
465
466 reg->flowBegin.plane = colorPlane;
467
469
470 if (oMsg == NULL || rMsg == NULL || gMsg == NULL || bMsg == NULL) {
471 dmtxMessageDestroy(&oMsg);
472 dmtxMessageDestroy(&rMsg);
473 dmtxMessageDestroy(&gMsg);
474 dmtxMessageDestroy(&bMsg);
475 return NULL;
476 }
477
478 offset = 0;
479 memcpy(oMsg->output + offset, rMsg->output, rMsg->outputIdx);
480 offset += rMsg->outputIdx;
481 memcpy(oMsg->output + offset, gMsg->output, gMsg->outputIdx);
482 offset += gMsg->outputIdx;
483 memcpy(oMsg->output + offset, bMsg->output, bMsg->outputIdx);
484 offset += bMsg->outputIdx;
485
486 oMsg->outputIdx = offset;
487
488 dmtxMessageDestroy(&rMsg);
489 dmtxMessageDestroy(&gMsg);
490 dmtxMessageDestroy(&bMsg);
491
492 return oMsg;
493}
494
499extern unsigned char *dmtxDecodeCreateDiagnostic(DmtxDecode *dec, int *totalBytes, int *headerBytes, int style)
500{
501 int i, row, col;
502 int width, height;
503 int widthDigits, heightDigits;
504 int count, channelCount;
505 int rgb[3];
506 double shade;
507 unsigned char *pnm, *output, *cache;
508
509 width = dmtxDecodeGetProp(dec, DmtxPropWidth);
510 height = dmtxDecodeGetProp(dec, DmtxPropHeight);
511 channelCount = dmtxImageGetProp(dec->image, DmtxPropChannelCount);
512
513 style = 1; /* this doesn't mean anything yet */
514
515 /* Count width digits */
516 for (widthDigits = 0, i = width; i > 0; i /= 10) {
517 widthDigits++;
518 }
519
520 /* Count height digits */
521 for (heightDigits = 0, i = height; i > 0; i /= 10) {
522 heightDigits++;
523 }
524
525 *headerBytes = widthDigits + heightDigits + 9;
526 *totalBytes = *headerBytes + width * height * 3;
527
528 pnm = (unsigned char *)malloc(*totalBytes);
529 if (pnm == NULL) {
530 return NULL;
531 }
532
533#if defined(_MSC_VER) && (_MSC_VER < 1700)
534 count = sprintf_s((char *)pnm, *headerBytes + 1, "P6\n%d %d\n255\n", width, height);
535#else
536 count = snprintf((char *)pnm, *headerBytes + 1, "P6\n%d %d\n255\n", width, height);
537#endif
538
539 if (count != *headerBytes) {
540 free(pnm);
541 return NULL;
542 }
543
544 output = pnm + (*headerBytes);
545 for (row = height - 1; row >= 0; row--) {
546 for (col = 0; col < width; col++) {
547 cache = dmtxDecodeGetCache(dec, col, row);
548 if (cache == NULL) {
549 rgb[0] = 0;
550 rgb[1] = 0;
551 rgb[2] = 128;
552 } else if (*cache & 0x40) {
553 rgb[0] = 255;
554 rgb[1] = 0;
555 rgb[2] = 0;
556 } else {
557 shade = (*cache & 0x80) ? 0.0 : 0.7;
558 for (i = 0; i < 3; i++) {
559 if (i < channelCount) {
560 dmtxDecodeGetPixelValue(dec, col, row, i, &rgb[i]);
561 } else {
562 dmtxDecodeGetPixelValue(dec, col, row, 0, &rgb[i]);
563 }
564
565 rgb[i] += (int)(shade * (double)(255 - rgb[i]) + 0.5);
566 if (rgb[i] > 255) {
567 rgb[i] = 255;
568 }
569 }
570 }
571 *(output++) = (unsigned char)rgb[0];
572 *(output++) = (unsigned char)rgb[1];
573 *(output++) = (unsigned char)rgb[2];
574 }
575 }
576 DmtxAssert(output == pnm + *totalBytes);
577
578 return pnm;
579}
580
596static void tallyModuleJumps(DmtxDecode *dec, DmtxRegion *reg, INOUT int tally[][24], int xOrigin, int yOrigin,
597 int mapWidth, int mapHeight, DmtxDirection dir)
598{
599 int extent, weight;
600 int travelStep;
601 int symbolRow, symbolCol;
602 int mapRow, mapCol;
603 int lineStart, lineStop;
604 int travelStart, travelStop;
605 int *line, *travel;
606 int jumpThreshold;
607 int darkOnLight; // 白底黑码:1,黑底白码:0
608 int color;
609 int statusPrev, statusModule;
610 int tPrev, tModule;
611
612 DmtxAssert(dir == DmtxDirUp || dir == DmtxDirLeft || dir == DmtxDirDown || dir == DmtxDirRight);
613
614 travelStep = (dir == DmtxDirUp || dir == DmtxDirRight) ? 1 : -1;
615
616 /* Abstract row and column progress using pointers to allow grid traversal in all 4 directions using same logic */
617
618 if ((dir & DmtxDirHorizontal) != 0x00) {
619 line = &symbolRow;
620 travel = &symbolCol;
621 extent = mapWidth;
622 lineStart = yOrigin;
623 lineStop = yOrigin + mapHeight;
624 travelStart = (travelStep == 1) ? xOrigin - 1 : xOrigin + mapWidth;
625 travelStop = (travelStep == 1) ? xOrigin + mapWidth : xOrigin - 1;
626 } else {
628 line = &symbolCol;
629 travel = &symbolRow;
630 extent = mapHeight;
631 lineStart = xOrigin;
632 lineStop = xOrigin + mapWidth;
633 travelStart = (travelStep == 1) ? yOrigin - 1 : yOrigin + mapHeight;
634 travelStop = (travelStep == 1) ? yOrigin + mapHeight : yOrigin - 1;
635 }
636
637 darkOnLight = (int)(reg->offColor > reg->onColor);
638 jumpThreshold = abs((int)(0.4 * (reg->offColor - reg->onColor) + 0.5));
639
640 DmtxAssert(jumpThreshold >= 0);
641
642 for (*line = lineStart; *line < lineStop; (*line)++) {
643 /* Capture tModule for each leading border module as normal but decide status based on predictable barcode
644 * border pattern */
645
646 *travel = travelStart;
647 color = readModuleColor(dec, reg, symbolRow, symbolCol, reg->sizeIdx, reg->flowBegin.plane);
648 tModule = (darkOnLight) ? reg->offColor - color : color - reg->offColor;
649
650 statusModule = (travelStep == 1 || (*line & 0x01) == 0) ? DmtxModuleOnRGB : DmtxModuleOff;
651
652 weight = extent;
653
654 while ((*travel += travelStep) != travelStop) {
655 tPrev = tModule;
656 statusPrev = statusModule;
657
658 /* For normal data-bearing modules capture color and decide module status based on comparison to previous
659 * "known" module */
660
661 color = readModuleColor(dec, reg, symbolRow, symbolCol, reg->sizeIdx, reg->flowBegin.plane);
662 tModule = (darkOnLight) ? reg->offColor - color : color - reg->offColor;
663
664 /* 和上一次的结果数据对比,如果在加减Threshold后满足条件,那么认为确实有一次跳变 */
665 if (statusPrev == DmtxModuleOnRGB) {
666 if (tModule < tPrev - jumpThreshold) {
667 statusModule = DmtxModuleOff;
668 } else {
669 statusModule = DmtxModuleOnRGB;
670 }
671 } else if (statusPrev == DmtxModuleOff) {
672 if (tModule > tPrev + jumpThreshold) {
673 statusModule = DmtxModuleOnRGB;
674 } else {
675 statusModule = DmtxModuleOff;
676 }
677 }
678
679 mapRow = symbolRow - yOrigin;
680 mapCol = symbolCol - xOrigin;
681 DmtxAssert(mapRow < 24 && mapCol < 24);
682
683 if (statusModule == DmtxModuleOnRGB) {
684 tally[mapRow][mapCol] += (2 * weight); // 对于bit为1的码元位置进行记录
685 }
686
687 weight--;
688 }
689
690 DmtxAssert(weight == 0);
691 }
692}
693
706{
707 // dmtxLogDebug("libdmtx::populateArrayFromMatrix()");
708 int weightFactor;
709 int mapWidth, mapHeight;
710 int xRegionTotal, yRegionTotal;
711 int xRegionCount, yRegionCount;
712 int xOrigin, yOrigin;
713 int mapCol, mapRow;
714 int colTmp, rowTmp, idx;
715 int tally[24][24]; /* 单个区块最大不会超过24×24,直接以最大分配 */
716
717 /* memset(msg->array, 0x00, msg->arraySize); */
718
719 /* 获取条形码中两个方向的区块数。当码元数目超过26×26(对于数据,码元数目超过24×24)时,它会划分为区块 */
722
723 /* 获取区块数据区尺寸(不包括边界模块) */
726
727 weightFactor = 2 * (mapHeight + mapWidth + 2);
728 DmtxAssert(weightFactor > 0);
729
730 // dmtxLogInfo("libdmtx::populateArrayFromMatrix::reg->sizeIdx: %d", reg->sizeIdx);
731 // dmtxLogInfo("libdmtx::populateArrayFromMatrix::reg->flowBegin.plane: %d", reg->flowBegin.plane);
732 // dmtxLogInfo("libdmtx::populateArrayFromMatrix::reg->onColor: %d", reg->onColor);
733 // dmtxLogInfo("libdmtx::populateArrayFromMatrix::reg->offColor: %d", reg->offColor);
734 // dmtxLogInfo("libdmtx::populateArrayFromMatrix::xRegionTotal: %d", xRegionTotal);
735 // dmtxLogInfo("libdmtx::populateArrayFromMatrix::yRegionTotal: %d", yRegionTotal);
736 // dmtxLogInfo("libdmtx::populateArrayFromMatrix::mapWidth: %d", mapWidth);
737 // dmtxLogInfo("libdmtx::populateArrayFromMatrix::mapHeight: %d", mapHeight);
738 // dmtxLogInfo("libdmtx::populateArrayFromMatrix::weightFactor: %d", weightFactor);
739 // reg->fit2raw[1][0] = 0;
740 // reg->fit2raw[0][1] = 0;
741 // reg->fit2raw[0][2] = 0;
742 // reg->fit2raw[2][2] = 1;
743 // reg->fit2raw[1][2] = 0;
744 // reg->fit2raw[2][0] = 10; // translation
745 // reg->fit2raw[2][1] = 10; // translation
746 // reg->fit2raw[0][0] = 60; // scale
747 // reg->fit2raw[1][1] = 60; // scale
748 // dmtxMatrix3Print(reg->fit2raw);
749
750 /* 每个方向上每个区域的计数模块变化 Tally module changes for each region in each direction */
751 for (yRegionCount = 0; yRegionCount < yRegionTotal; yRegionCount++) {
752 /* 在符号坐标中映射区域原点的Y位置 Y location of mapping region origin in symbol coordinates */
753 yOrigin = yRegionCount * (mapHeight + 2) + 1;
754
755 for (xRegionCount = 0; xRegionCount < xRegionTotal; xRegionCount++) {
756 /* 在符号坐标中映射区域原点的X位置 X location of mapping region origin in symbol coordinates */
757 xOrigin = xRegionCount * (mapWidth + 2) + 1;
758
759 // dmtxLogInfo("libdmtx::populateArrayFromMatrix::xOrigin: %d", xOrigin);
760
780 memset(tally, 0x00, sizeof(int) * 24 * 24);
781 tallyModuleJumps(dec, reg, tally, xOrigin, yOrigin, mapWidth, mapHeight, DmtxDirUp);
782 tallyModuleJumps(dec, reg, tally, xOrigin, yOrigin, mapWidth, mapHeight, DmtxDirLeft);
783 tallyModuleJumps(dec, reg, tally, xOrigin, yOrigin, mapWidth, mapHeight, DmtxDirDown);
784 tallyModuleJumps(dec, reg, tally, xOrigin, yOrigin, mapWidth, mapHeight, DmtxDirRight);
785
786 /* 根据记录内容(tally)更新array的内容 */
787 for (mapRow = 0; mapRow < mapHeight; mapRow++) {
788 // for(mapRow = mapHeight-1; mapRow >= 0; mapRow--) {
789 for (mapCol = 0; mapCol < mapWidth; mapCol++) {
790 rowTmp = (yRegionCount * mapHeight) + mapRow;
791 rowTmp = yRegionTotal * mapHeight - rowTmp - 1;
792 colTmp = (xRegionCount * mapWidth) + mapCol;
793 idx = (rowTmp * xRegionTotal * mapWidth) + colTmp;
794
795 // printf("%c ", tally[mapRow][mapCol] == DmtxModuleOff ? '0' : '1');
796 if (tally[mapRow][mapCol] / (double)weightFactor >= 0.5) {
797 msg->array[idx] = DmtxModuleOnRGB;
798 // printf("1 ");
799 } else {
800 msg->array[idx] = DmtxModuleOff;
801 // printf("0 ");
802 }
803 // printf("libdmtx::populateArrayFromMatrix::idx: %d @ (%d,%d)\n", idx, mapCol, mapRow);
804
805 msg->array[idx] |= DmtxModuleAssigned; // 标记为已分配
806 }
807 // printf("\n");
808 }
809 }
810 }
811
812 return DmtxPass;
813}
libdmtx - Data Matrix Encoding/Decoding Library Copyright 2008, 2009 Mike Laughton.
#define DmtxPassFail
Definition dmtx.h:42
#define DmtxFormatMosaic
Definition dmtx.h:51
@ DmtxPropEdgeThresh
Definition dmtx.h:193
@ DmtxPropXmax
ROI X坐标最大值(如果未设置则为图像宽度-1)
Definition dmtx.h:208
@ DmtxPropSquareDevn
Definition dmtx.h:191
@ DmtxPropEdgeMin
Definition dmtx.h:188
@ DmtxPropXmin
ROI X坐标最小值(如果未设置则为0)
Definition dmtx.h:207
@ DmtxPropEdgeMax
Definition dmtx.h:189
@ DmtxPropYmin
ROI Y坐标最小值(如果未设置则为0)
Definition dmtx.h:209
@ DmtxPropWidth
图像宽度
Definition dmtx.h:196
@ DmtxPropSymbolSize
Definition dmtx.h:192
@ DmtxPropChannelCount
图像通道数
Definition dmtx.h:204
@ DmtxPropHeight
图像高度
Definition dmtx.h:197
@ DmtxPropFnc1
Definition dmtx.h:185
@ DmtxPropScale
图像缩放比例
Definition dmtx.h:211
@ DmtxPropYmax
ROI Y坐标最大值(如果未设置则为图像高度-1)
Definition dmtx.h:210
@ DmtxPropScanGap
Definition dmtx.h:190
int dmtxGetSymbolAttribute(int attribute, int sizeIdx)
根据规格索引返回二维码规格各个参数
Definition dmtxsymbol.c:45
#define DmtxModuleOnRed
Definition dmtx.h:57
#define DmtxModuleAssigned
已分配
Definition dmtx.h:63
enum DmtxDirection_enum DmtxDirection
DmtxPassFail dmtxMessageDestroy(DmtxMessage **msg)
Free memory previously allocated for message.
Definition dmtxmessage.c:87
@ DmtxSymAttribHorizDataRegions
水平方向区块个数
Definition dmtx.h:158
@ DmtxSymAttribVertDataRegions
垂直方向区块个数
Definition dmtx.h:159
@ DmtxSymAttribDataRegionCols
单区块二维码数据区码元列数(不包括L形框和点线)
Definition dmtx.h:157
@ DmtxSymAttribDataRegionRows
单区块二维码数据区码元行数(不包括L形框和点线)
Definition dmtx.h:156
#define DmtxPass
Definition dmtx.h:43
#define DmtxFormatMatrix
Definition dmtx.h:50
#define DmtxModuleOnBlue
Definition dmtx.h:59
#define DmtxUndefined
Definition dmtx.h:40
#define INOUT
Definition dmtx.h:76
#define DmtxModuleOnRGB
OnRed | OnGreen | OnBlue.
Definition dmtx.h:60
@ DmtxDirDown
Definition dmtx.h:144
@ DmtxDirRight
Definition dmtx.h:145
@ DmtxDirUp
Definition dmtx.h:142
@ DmtxDirHorizontal
Definition dmtx.h:146
@ DmtxDirLeft
Definition dmtx.h:143
@ DmtxDirVertical
Definition dmtx.h:147
DmtxPassFail dmtxMatrix3VMultiplyBy(INOUT DmtxVector2 *v, DmtxMatrix3 m)
将向量与矩阵相乘
DmtxMessage * dmtxMessageCreate(int sizeIdx, int symbolFormat)
Allocate memory for message.
Definition dmtxmessage.c:30
int dmtxImageGetProp(DmtxImage *img, int prop)
获取图像属性
Definition dmtximage.c:228
DmtxPassFail dmtxImageGetPixelValue(DmtxImage *img, int x, int y, int channel, OUT int *value)
#define DmtxFail
Definition dmtx.h:44
#define DmtxModuleOnGreen
绿
Definition dmtx.h:58
#define M_PI
Definition dmtx.h:33
#define OUT
Definition dmtx.h:75
#define DmtxModuleOff
bit0
Definition dmtx.h:56
@ DmtxSymbolShapeAuto
Definition dmtx.h:102
unsigned char * dmtxDecodeCreateDiagnostic(DmtxDecode *dec, int *totalBytes, int *headerBytes, int style)
Definition dmtxdecode.c:499
static void tallyModuleJumps(DmtxDecode *dec, DmtxRegion *reg, INOUT int tally[][24], int xOrigin, int yOrigin, int mapWidth, int mapHeight, DmtxDirection dir)
通过指定方向对判断bit为1的码元位置记录对应的值
Definition dmtxdecode.c:596
unsigned char * dmtxDecodeGetCache(DmtxDecode *dec, int x, int y)
Returns xxx.
Definition dmtxdecode.c:211
DmtxDecode * dmtxDecodeCreate(DmtxImage *img, int scale)
Initialize decode struct with default values.
Definition dmtxdecode.c:32
static DmtxPassFail populateArrayFromMatrix(DmtxDecode *dec, DmtxRegion *reg, OUT DmtxMessage *msg)
根据模块颜色填充数组以确定码字值。
Definition dmtxdecode.c:705
DmtxMessage * dmtxDecodeMosaicRegion(DmtxDecode *dec, DmtxRegion *reg, int fix)
Convert fitted Data Mosaic region into a decoded message.
Definition dmtxdecode.c:436
DmtxPassFail dmtxDecodeGetPixelValue(DmtxDecode *dec, int x, int y, int channel, OUT int *value)
获取图像像素
Definition dmtxdecode.c:233
DmtxPassFail dmtxDecodeDestroy(DmtxDecode **dec)
Deinitialize decode struct.
Definition dmtxdecode.c:77
DmtxMessage * dmtxDecodePopulatedArray(int sizeIdx, INOUT DmtxMessage *msg, int fix)
从DataMatrix数据区二进制矩阵解码,并将结果写入msg->output
Definition dmtxdecode.c:390
DmtxPassFail dmtxDecodeSetProp(DmtxDecode *dec, int prop, int value)
Set decoding behavior property.
Definition dmtxdecode.c:101
static void cacheFillQuad(DmtxDecode *dec, DmtxPixelLoc p0, DmtxPixelLoc p1, DmtxPixelLoc p2, DmtxPixelLoc p3)
Fill the region covered by the quadrilateral given by (p0,p1,p2,p3) in the cache.
Definition dmtxdecode.c:272
int dmtxDecodeGetProp(DmtxDecode *dec, int prop)
Get decoding behavior property.
Definition dmtxdecode.c:166
DmtxMessage * dmtxDecodeMatrixRegion(DmtxDecode *dec, DmtxRegion *reg, int fix)
解码拟合的二维码区域
Definition dmtxdecode.c:336
DmtxPassFail decodeDataStream(DmtxMessage *msg, int sizeIdx, unsigned char *outputStart)
Translate encoded data stream into final output.
static int modulePlacementEcc200(INOUT unsigned char *modules, OUT unsigned char *codewords, int sizeIdx, int moduleOnColor)
通过DataMatrix数据区的二进制矩阵,根据DataMatrix的排列规则,得到码字(codewords)
static DmtxPassFail rsDecode(unsigned char *code, int sizeIdx, int fix)
Decode xyz.
static DmtxPassFail bresLineStep(DmtxBresLine *line, int travel, int outward)
static int readModuleColor(DmtxDecode *dec, DmtxRegion *reg, int symbolRow, int symbolCol, int sizeIdx, int colorPlane)
读取模块(码元)颜色值
Definition dmtxregion.c:646
static DmtxBresLine bresLineInit(DmtxPixelLoc loc0, DmtxPixelLoc loc1, DmtxPixelLoc locInside)
static DmtxScanGrid initScanGrid(DmtxDecode *dec)
初始化扫描网格
libdmtx - Data Matrix Encoding/Decoding Library Copyright 2008, 2009 Mike Laughton.
#define DmtxAssert(expr)
Definition dmtxstatic.h:96
#define min(X, Y)
Definition dmtxstatic.h:62
#define max(X, Y)
Definition dmtxstatic.h:65
DmtxBresLine.
DmtxDecode.
DataMatrix编码内容
Definition dmtx.h:421
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
像素坐标
Definition dmtx.h:268
int plane
多通道平面索引
Definition dmtx.h:343
二维码区域(包围框)
Definition dmtx.h:369
int offColor
代表bit0的颜色值
Definition dmtx.h:405
int sizeIdx
二维码类型索引,总共有 DmtxSymbolSquareCount + DmtxSymbolRectCount 种
Definition dmtx.h:406
DmtxPointFlow flowBegin
搜索起点,十字搜索抛出的点
Definition dmtx.h:378
int onColor
代表bit1的颜色值
Definition dmtx.h:404
DmtxMatrix3 fit2raw
3x3 变换矩阵,从二维码坐标系到图像坐标系
Definition dmtx.h:414
二维向量
Definition dmtx.h:277