📄 dmtxread.c
字号:
/*libdmtx - Data Matrix Encoding/Decoding LibraryCopyright (c) 2008 Mike LaughtonCopyright (c) 2008 Ryan RaaschCopyright (c) 2008 Olivier GuilyardiThis library is free software; you can redistribute it and/ormodify it under the terms of the GNU Lesser General PublicLicense as published by the Free Software Foundation; eitherversion 2.1 of the License, or (at your option) any later version.This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNULesser General Public License for more details.You should have received a copy of the GNU Lesser General PublicLicense along with this library; if not, write to the Free SoftwareFoundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USAContact: mike@dragonflylogic.com*//* $Id: dmtxread.c 514 2008-11-19 17:10:44Z mblaughton $ */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <getopt.h>#include <errno.h>#include <ctype.h>#include <math.h>#include <stdarg.h>#include <assert.h>#include <sysexits.h>#include <magick/api.h>#include <dmtx.h>#include "dmtxread.h"#include "../common/dmtxutil.h"char *programName;/** * @brief Main function for the dmtxread Data Matrix scanning utility. * @param argc count of arguments passed from command line * @param argv list of argument passed strings from command line * @return Numeric exit code */intmain(int argc, char *argv[]){ int err; int fileIndex; int pageIndex; int imgWidth, imgHeight; int fileScanCount, globalScanCount; int nFiles; UserOptions opt; DmtxTime msec, *timeout; DmtxImage *img; DmtxDecode dec; DmtxRegion reg; DmtxMessage *msg; ImageReader reader; SetOptionDefaults(&opt); InitializeMagick(*argv); err = HandleArgs(&opt, &fileIndex, &argc, &argv); if(err != DMTX_SUCCESS) ShowUsage(EX_USAGE); timeout = (opt.timeoutMS == -1) ? NULL : &msec; reader.image = NULL; nFiles = argc - fileIndex; globalScanCount = 0; /* Loop once for each page of each image listed in parameters */ for(pageIndex = 0; fileIndex < argc || (nFiles == 0 && fileIndex == argc);) { /* Reset timeout for each new image */ if(timeout != NULL) msec = dmtxTimeAdd(dmtxTimeNow(), opt.timeoutMS); /* Open image file/stream */ if(!reader.image) { if(argc == fileIndex) OpenImage(&reader, "-", opt.resolution); else OpenImage(&reader, argv[fileIndex], opt.resolution); if(!reader.image) { fileIndex++; continue; } } /* Read next image page (many formats are single-page only) */ img = ReadImagePage(&reader, pageIndex++); /* If requested page did not load then move to the next image */ if(img == NULL) { CloseImage(&reader); fileIndex++; pageIndex = 0; continue; } imgWidth = dmtxImageGetProp(img, DmtxPropWidth); imgHeight = dmtxImageGetProp(img, DmtxPropHeight); assert(img->pageCount > 0 && pageIndex <= img->pageCount); /* Initialize decode struct for newly loaded image */ dec = dmtxDecodeStructInit(img); err = dmtxDecodeSetProp(&dec, DmtxPropScanGap, opt.scanGap); assert(err == DMTX_SUCCESS); if(opt.edgeMin != -1) { err = dmtxDecodeSetProp(&dec, DmtxPropEdgeMin, opt.edgeMin); assert(err == DMTX_SUCCESS); } if(opt.edgeMax != -1) { err = dmtxDecodeSetProp(&dec, DmtxPropEdgeMax, opt.edgeMax); assert(err == DMTX_SUCCESS); } if(opt.squareDevn != -1) { err = dmtxDecodeSetProp(&dec, DmtxPropSquareDevn, opt.squareDevn); assert(err == DMTX_SUCCESS); } err = dmtxDecodeSetProp(&dec, DmtxPropSymbolSize, opt.sizeIdxExpected); assert(err == DMTX_SUCCESS); err = dmtxDecodeSetProp(&dec, DmtxPropEdgeThresh, opt.edgeThresh); assert(err == DMTX_SUCCESS); if(opt.xMin) { err = dmtxDecodeSetProp(&dec, DmtxPropXmin, ScaleNumberString(opt.xMin, imgWidth)); assert(err == DMTX_SUCCESS); } if(opt.xMax) { err = dmtxDecodeSetProp(&dec, DmtxPropXmax, ScaleNumberString(opt.xMax, imgWidth)); assert(err == DMTX_SUCCESS); } if(opt.yMin) { err = dmtxDecodeSetProp(&dec, DmtxPropYmin, ScaleNumberString(opt.yMin, imgHeight)); assert(err == DMTX_SUCCESS); } if(opt.yMax) { err = dmtxDecodeSetProp(&dec, DmtxPropYmax, ScaleNumberString(opt.yMax, imgHeight)); assert(err == DMTX_SUCCESS); } err = dmtxDecodeSetProp(&dec, DmtxPropShrinkMin, opt.shrinkMin); assert(err == DMTX_SUCCESS); err = dmtxDecodeSetProp(&dec, DmtxPropShrinkMax, opt.shrinkMax); assert(err == DMTX_SUCCESS); /* Loop once for each detected barcode region */ for(fileScanCount = 0;;) { /* Find next barcode region within image, but do not decode yet */ reg = dmtxDecodeFindNextRegion(&dec, timeout); /* Finished file or ran out of time before finding another region */ if(reg.found != DMTX_REGION_FOUND) break; /* Decode region based on requested barcode mode */ if(opt.mosaic) msg = dmtxDecodeMosaicRegion(img, ®, opt.correctionsMax); else msg = dmtxDecodeMatrixRegion(img, ®, opt.correctionsMax); if(msg == NULL) continue; PrintDecodedOutput(&opt, img, ®, msg, pageIndex); fileScanCount++; dmtxMessageFree(&msg); if(opt.stopAfter != -1 && fileScanCount >= opt.stopAfter) break; } globalScanCount += fileScanCount; if(opt.diagnose) WriteDiagnosticImage(&dec, ®, "debug.pnm"); dmtxDecodeStructDeInit(&dec); dmtxImageFree(&img); } DestroyMagick(); exit((globalScanCount > 0) ? EX_OK : 1);}/** * * */static voidSetOptionDefaults(UserOptions *opt){ UserOptions option; memset(&option, 0x00, sizeof(UserOptions)); /* Set default options */ option.codewords = 0; option.edgeMin = -1; option.edgeMax = -1; option.squareDevn = -1; option.scanGap = 2; option.timeoutMS = -1; option.newline = 0; option.resolution = NULL; option.sizeIdxExpected = DmtxSymbolShapeAuto; option.edgeThresh = 5; option.xMin = NULL; option.xMax = NULL; option.yMin = NULL; option.yMax = NULL; option.correctionsMax = -1; option.diagnose = 0; option.mosaic = 0; option.stopAfter = -1; option.pageNumber = 0; option.corners = 0; option.shrinkMin = 1; option.shrinkMax = 1; option.verbose = 0; *opt = option;}/** * @brief Set and validate user-requested options from command line arguments. * @param opt runtime options from defaults or command line * @param argcp pointer to argument count * @param argvp pointer to argument list * @param fileIndex pointer to index of first non-option arg (if successful) * @return DMTX_SUCCESS | DMTX_FAILURE */static intHandleArgs(UserOptions *opt, int *fileIndex, int *argcp, char **argvp[]){ int i; int err; int optchr; int longIndex; char *ptr; struct option longOptions[] = { {"codewords", no_argument, NULL, 'c'}, {"minimum-edge", required_argument, NULL, 'e'}, {"maximum-edge", required_argument, NULL, 'E'}, {"gap", required_argument, NULL, 'g'}, {"list-formats", no_argument, NULL, 'l'}, {"milliseconds", required_argument, NULL, 'm'}, {"newline", no_argument, NULL, 'n'}, {"square-deviation", required_argument, NULL, 'q'}, {"resolution", required_argument, NULL, 'r'}, {"symbol-size", required_argument, NULL, 's'}, {"threshold", required_argument, NULL, 't'}, {"x-range-min", required_argument, NULL, 'x'}, {"x-range-max", required_argument, NULL, 'X'}, {"y-range-min", required_argument, NULL, 'y'}, {"y-range-max", required_argument, NULL, 'Y'}, {"max-corrections", required_argument, NULL, 'C'}, {"diagnose", no_argument, NULL, 'D'}, {"mosaic", no_argument, NULL, 'M'}, {"stop-after", required_argument, NULL, 'N'}, {"page-number", no_argument, NULL, 'P'}, {"corners", no_argument, NULL, 'R'}, {"shrink", required_argument, NULL, 'S'}, {"verbose", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'V'}, {"help", no_argument, NULL, 0 }, {0, 0, 0, 0} }; programName = Basename((*argvp)[0]); *fileIndex = 0; for(;;) { optchr = getopt_long(*argcp, *argvp, "ce:E:g:lm:nq:r:s:t:x:X:y:Y:vC:DMN:PRS:V", longOptions, &longIndex); if(optchr == -1) break; switch(optchr) { case 0: /* --help */ ShowUsage(EX_OK); break; case 'l': /* --help */ ListImageFormats(); exit(EX_OK); break; case 'c': opt->codewords = 1; break; case 'e': err = StringToInt(&(opt->edgeMin), optarg, &ptr); if(err != DMTX_SUCCESS || opt->edgeMin <= 0 || *ptr != '\0') FatalError(EX_USAGE, _("Invalid edge length specified \"%s\""), optarg); break; case 'E': err = StringToInt(&(opt->edgeMax), optarg, &ptr); if(err != DMTX_SUCCESS || opt->edgeMax <= 0 || *ptr != '\0') FatalError(EX_USAGE, _("Invalid edge length specified \"%s\""), optarg); break; case 'g': err = StringToInt(&(opt->scanGap), optarg, &ptr); if(err != DMTX_SUCCESS || opt->scanGap <= 0 || *ptr != '\0') FatalError(EX_USAGE, _("Invalid gap specified \"%s\""), optarg); break; case 'm': err = StringToInt(&(opt->timeoutMS), optarg, &ptr); if(err != DMTX_SUCCESS || opt->timeoutMS < 0 || *ptr != '\0') FatalError(EX_USAGE, _("Invalid timeout (in milliseconds) specified \"%s\""), optarg); break; case 'n': opt->newline = 1; break; case 'q': err = StringToInt(&(opt->squareDevn), optarg, &ptr); if(err != DMTX_SUCCESS || *ptr != '\0' || opt->squareDevn < 0 || opt->squareDevn > 90) FatalError(EX_USAGE, _("Invalid squareness deviation specified \"%s\""), optarg); break; case 'r': opt->resolution = optarg; break; case 's': /* Determine correct barcode size and/or shape */ if(*optarg == 'a') { opt->sizeIdxExpected = DmtxSymbolShapeAuto; } else if(*optarg == 's') { opt->sizeIdxExpected = DmtxSymbolSquareAuto; } else if(*optarg == 'r') { opt->sizeIdxExpected = DmtxSymbolRectAuto; } else { for(i = 0; i < DMTX_SYMBOL_SQUARE_COUNT + DMTX_SYMBOL_RECT_COUNT; i++) { if(strncmp(optarg, symbolSizes[i], 8) == 0) { opt->sizeIdxExpected = i; break; } } if(i == DMTX_SYMBOL_SQUARE_COUNT + DMTX_SYMBOL_RECT_COUNT) return DMTX_FAILURE; } break; case 't': err = StringToInt(&(opt->edgeThresh), optarg, &ptr); if(err != DMTX_SUCCESS || *ptr != '\0' || opt->edgeThresh < 1 || opt->edgeThresh > 100) FatalError(EX_USAGE, _("Invalid edge threshold specified \"%s\""), optarg); break; case 'x': opt->xMin = optarg; break; case 'X': opt->xMax = optarg; break; case 'y': opt->yMin = optarg; break; case 'Y': opt->yMax = optarg; break; case 'v': opt->verbose = 1; break; case 'C': err = StringToInt(&(opt->correctionsMax), optarg, &ptr); if(err != DMTX_SUCCESS || opt->correctionsMax < 0 || *ptr != '\0') FatalError(EX_USAGE, _("Invalid max corrections specified \"%s\""), optarg); break; case 'D': opt->diagnose = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -