⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dmtxregion.c

📁 Datamatrix二维码库和测试程序,运行于linux,仔细研究可以很容易转化成VC程序,有这就没必要化钱买个控件了,本人libdmtx-0.3版本转化过,的确可行,现在把找到该版本的libdmtx
💻 C
📖 第 1 页 / 共 4 页
字号:
/*libdmtx - Data Matrix Encoding/Decoding LibraryCopyright (c) 2008 Mike LaughtonThis 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: dmtxregion.c 514 2008-11-19 17:10:44Z mblaughton $ */#define DMTX_HOUGH_RES 180/** * @file dmtxregion.c * @brief Detect barcode regions * * This file contains region detection logic. *//** * @brief  Find next barcode region * @param  dec Pointer to DmtxDecode information struct * @param  timeout Pointer to timeout time (NULL if none) * @return Detected region (if found) */extern DmtxRegiondmtxDecodeFindNextRegion(DmtxDecode *dec, DmtxTime *timeout){   DmtxScanGrid *grid;   DmtxPixelLoc loc, locNext;   DmtxRegion   reg;/**   int size, i = 0;   char imagePath[128];*/   grid = &(dec->grid);   /* Continue scanning until we run out of time or run out of image */   for(loc = GetGridCoordinates(grid);; loc = locNext) {      /* Quit if grid has been completely traversed */      if(loc.status == DMTX_RANGE_EOF) {         reg.found = DMTX_REGION_EOF;         break;      }      /* First move away from this location to prevent repeat visits */      locNext = IncrementPixelProgress(grid);      /* Scan this pixel for presence of a valid barcode edge */      reg = dmtxRegionScanPixel(dec, loc);/**      if(reg.found == DMTX_REGION_FOUND || reg.found > DMTX_REGION_DROPPED_FINDER) {         size = snprintf(imagePath, 128, "debug_%06d.pnm", i++);         if(size >= 128)            exit(1);         WriteDiagnosticImage(dec, &reg, imagePath);      }*/      /* Found a barcode region? */      if(reg.found == DMTX_REGION_FOUND)         break;      /* Ran out of time? */      if(timeout != NULL && dmtxTimeExceeded(*timeout)) {         reg.found = DMTX_REGION_TIMEOUT;         break;      }   }   return reg;}/** * @brief  Scan individual pixel for presence of barcode edge * @param  dec Pointer to DmtxDecode information struct * @param  loc Pixel location * @return Detected region (if any) */extern DmtxRegiondmtxRegionScanPixel(DmtxDecode *dec, DmtxPixelLoc loc){   int offset;   DmtxRegion reg;   DmtxPointFlow flowBegin;   memset(&reg, 0x00, sizeof(DmtxRegion));   offset = dmtxImageGetOffset(dec->image, loc.X, loc.Y);/* if(offset == DMTX_BAD_OFFSET || dec->image->cache[offset] & 0x40) { */   if(offset == DMTX_BAD_OFFSET) {      reg.found = DMTX_REGION_NOT_FOUND;      return reg;   }   if((int)(dec->image->cache[offset] & 0x80) != 0x00) {      reg.found = DMTX_REGION_NOT_FOUND;      return reg;   }   /* Test for presence of any reasonable edge at this location */   flowBegin = MatrixRegionSeekEdge(dec, loc);   if(flowBegin.mag < 10) {      reg.found = DMTX_REGION_DROPPED_EDGE;      return reg;   }   /* Determine barcode orientation */   if(MatrixRegionOrientation(dec, &reg, flowBegin) != DMTX_SUCCESS) {      reg.found = DMTX_REGION_DROPPED_FINDER;      return reg;   }   if(dmtxRegionUpdateXfrms(dec, &reg) != DMTX_SUCCESS) {      reg.found = DMTX_REGION_DROPPED_FINDER;      return reg;   }   /* Define top edge */   if(MatrixRegionAlignCalibEdge(dec, &reg, DmtxEdgeTop) != DMTX_SUCCESS) {      reg.found = DMTX_REGION_DROPPED_TOP;      return reg;   }   if(dmtxRegionUpdateXfrms(dec, &reg) != DMTX_SUCCESS) {      reg.found = DMTX_REGION_DROPPED_TOP;      return reg;   }   /* Define right edge */   if(MatrixRegionAlignCalibEdge(dec, &reg, DmtxEdgeRight) != DMTX_SUCCESS) {      reg.found = DMTX_REGION_DROPPED_RIGHT;      return reg;   }   if(dmtxRegionUpdateXfrms(dec, &reg) != DMTX_SUCCESS) {      reg.found = DMTX_REGION_DROPPED_RIGHT;      return reg;   }   CALLBACK_MATRIX(&reg);   /* Calculate the best fitting symbol size */   if(MatrixRegionFindSize(dec, &reg) != DMTX_SUCCESS) {      reg.found = DMTX_REGION_DROPPED_SIZE;      return reg;   }   /* Found a valid matrix region */   reg.found = DMTX_REGION_FOUND;   return reg;}/** * * */static DmtxPointFlowMatrixRegionSeekEdge(DmtxDecode *dec, DmtxPixelLoc loc){   int i;   int strongIdx;   DmtxPointFlow flow, flowPlane[3];   DmtxPointFlow flowPos, flowPosBack;   DmtxPointFlow flowNeg, flowNegBack;   /* Find whether red, green, or blue shows the strongest edge */   strongIdx = 0;   for(i = 0; i < 3; i++) {      flowPlane[i] = GetPointFlow(dec, i, loc, dmtxNeighborNone);      if(i > 0 && flowPlane[i].mag > flowPlane[strongIdx].mag)         strongIdx = i;   }   if(flowPlane[strongIdx].mag < 10)      return dmtxBlankEdge;   flow = flowPlane[strongIdx];   flowPos = FindStrongestNeighbor(dec, flow, +1);   flowNeg = FindStrongestNeighbor(dec, flow, -1);   if(flowPos.mag != 0 && flowNeg.mag != 0) {      flowPosBack = FindStrongestNeighbor(dec, flowPos, -1);      flowNegBack = FindStrongestNeighbor(dec, flowNeg, +1);      if(flowPos.arrive == (flowPosBack.arrive+4)%8 &&            flowNeg.arrive == (flowNegBack.arrive+4)%8) {         flow.arrive = dmtxNeighborNone;         CALLBACK_POINT_PLOT(flow.loc, 1, 1, DMTX_DISPLAY_SQUARE);         return flow;      }   }   return dmtxBlankEdge;}/** * * */static intMatrixRegionOrientation(DmtxDecode *dec, DmtxRegion *reg, DmtxPointFlow begin){   int err;   int cross;   int minArea;   int scale;   int symbolShape;   int maxDiagonal;   DmtxBestLine line1x, line2x;   DmtxBestLine line2n, line2p;   DmtxFollow fTmp;   if(dec->sizeIdxExpected == DmtxSymbolSquareAuto ||         (dec->sizeIdxExpected >= DmtxSymbol10x10 &&         dec->sizeIdxExpected <= DmtxSymbol144x144))      symbolShape = DmtxSymbolSquareAuto;   else if(dec->sizeIdxExpected == DmtxSymbolRectAuto ||         (dec->sizeIdxExpected >= DmtxSymbol8x18 &&         dec->sizeIdxExpected <= DmtxSymbol16x48))      symbolShape = DmtxSymbolRectAuto;   else      symbolShape = DmtxSymbolShapeAuto;   if(dec->edgeMax != -1) {      if(symbolShape == DmtxSymbolRectAuto)         maxDiagonal = (int)(1.23 * dec->edgeMax + 0.5); /* sqrt(5/4) + 10% */      else         maxDiagonal = (int)(1.56 * dec->edgeMax + 0.5); /* sqrt(2) + 10% */   }   else {      maxDiagonal = -1;   }   /* Follow to end in both directions */   err = TrailBlazeContinuous(dec, reg, begin, maxDiagonal);   if(err == DMTX_FAILURE || reg->stepsTotal < 40) {      TrailClear(dec, reg, 0x40);      return DMTX_FAILURE;   }   /* Filter out region candidates that are smaller than expected */   if(dec->edgeMin != -1) {      scale = dmtxImageGetProp(dec->image, DmtxPropScale);      if(symbolShape == DmtxSymbolSquareAuto)         minArea = (dec->edgeMin * dec->edgeMin)/(scale * scale);      else         minArea = (2 * dec->edgeMin * dec->edgeMin)/(scale * scale);      if((reg->boundMax.X - reg->boundMin.X) * (reg->boundMax.Y - reg->boundMin.Y) < minArea) {         TrailClear(dec, reg, 0x40);         return DMTX_FAILURE;      }   }   line1x = FindBestSolidLine(dec, reg, 0, 0, +1, -1);   if(line1x.mag < 5) {      TrailClear(dec, reg, 0x40);      return DMTX_FAILURE;   }   err = FindTravelLimits(dec, reg, &line1x);   if(line1x.distSq < 100 || line1x.devn * 10 >= sqrt((double)line1x.distSq)) {      TrailClear(dec, reg, 0x40);      return DMTX_FAILURE;   }   assert(line1x.stepPos >= line1x.stepNeg);   fTmp = FollowSeek(dec, reg, line1x.stepPos + 5);   line2p = FindBestSolidLine(dec, reg, fTmp.step, line1x.stepNeg, +1, line1x.angle);   fTmp = FollowSeek(dec, reg, line1x.stepNeg - 5);   line2n = FindBestSolidLine(dec, reg, fTmp.step, line1x.stepPos, -1, line1x.angle);   if(max(line2p.mag, line2n.mag) < 5)      return DMTX_FAILURE;   if(line2p.mag > line2n.mag) {      line2x = line2p;      err = FindTravelLimits(dec, reg, &line2x);      if(line2x.distSq < 100 || line2x.devn * 10 >= sqrt((double)line2x.distSq))         return DMTX_FAILURE;      cross = ((line1x.locPos.X - line1x.locNeg.X) * (line2x.locPos.Y - line2x.locNeg.Y)) -            ((line1x.locPos.Y - line1x.locNeg.Y) * (line2x.locPos.X - line2x.locNeg.X));      if(cross > 0) {         /* Condition 2 */         reg->polarity = +1;         reg->locR = line2x.locPos;         reg->stepR = line2x.stepPos;         reg->locT = line1x.locNeg;         reg->stepT = line1x.stepNeg;         reg->leftLoc = line1x.locBeg;         reg->leftAngle = line1x.angle;         reg->bottomLoc = line2x.locBeg;         reg->bottomAngle = line2x.angle;         reg->leftLine = line1x;         reg->bottomLine = line2x;      }      else {         /* Condition 3 */         reg->polarity = -1;         reg->locR = line1x.locNeg;         reg->stepR = line1x.stepNeg;         reg->locT = line2x.locPos;         reg->stepT = line2x.stepPos;         reg->leftLoc = line2x.locBeg;         reg->leftAngle = line2x.angle;         reg->bottomLoc = line1x.locBeg;         reg->bottomAngle = line1x.angle;         reg->leftLine = line2x;         reg->bottomLine = line1x;      }   }   else {      line2x = line2n;      err = FindTravelLimits(dec, reg, &line2x);      if(line2x.distSq < 100 || line2x.devn / sqrt((double)line2x.distSq) >= 0.1)         return DMTX_FAILURE;      cross = ((line1x.locNeg.X - line1x.locPos.X) * (line2x.locNeg.Y - line2x.locPos.Y)) -            ((line1x.locNeg.Y - line1x.locPos.Y) * (line2x.locNeg.X - line2x.locPos.X));      if(cross > 0) {         /* Condition 1 */         reg->polarity = -1;         reg->locR = line2x.locNeg;         reg->stepR = line2x.stepNeg;         reg->locT = line1x.locPos;         reg->stepT = line1x.stepPos;         reg->leftLoc = line1x.locBeg;         reg->leftAngle = line1x.angle;         reg->bottomLoc = line2x.locBeg;         reg->bottomAngle = line2x.angle;         reg->leftLine = line1x;         reg->bottomLine = line2x;      }      else {         /* Condition 4 */         reg->polarity = +1;         reg->locR = line1x.locPos;         reg->stepR = line1x.stepPos;         reg->locT = line2x.locNeg;         reg->stepT = line2x.stepNeg;         reg->leftLoc = line2x.locBeg;         reg->leftAngle = line2x.angle;         reg->bottomLoc = line1x.locBeg;         reg->bottomAngle = line1x.angle;         reg->leftLine = line2x;         reg->bottomLine = line1x;      }   }/* CALLBACK_POINT_PLOT(reg->locR, 2, 1, DMTX_DISPLAY_SQUARE);   CALLBACK_POINT_PLOT(reg->locT, 2, 1, DMTX_DISPLAY_SQUARE); */   reg->leftKnown = reg->bottomKnown = 1;   return DMTX_SUCCESS;}/** * * */static longDistanceSquared(DmtxPixelLoc a, DmtxPixelLoc b){   long xDelta, yDelta;   xDelta = a.X - b.X;   yDelta = a.Y - b.Y;   return (xDelta * xDelta) + (yDelta * yDelta);}/** * * */static unsigned char *GetCacheAddress(DmtxDecode *dec, int x, int y){   int offset;   offset = dmtxImageGetOffset(dec->image, x, y);   if(offset == DMTX_BAD_OFFSET)      return NULL;   return &(dec->image->cache[offset]);}/** * * */extern intdmtxRegionUpdateCorners(DmtxDecode *dec, DmtxRegion *reg, DmtxVector2 p00,      DmtxVector2 p10, DmtxVector2 p11, DmtxVector2 p01){   DmtxVector2 vOT, vOR, vTX, vRX, vTmp;   double tx, ty, phi, shx, scx, scy, skx, sky;   double dimOT, dimOR, dimTX, dimRX, ratio;   DmtxMatrix3 m, mtxy, mphi, mshx, mscx, mscy, mscxy, msky, mskx;   if(dmtxImageContainsFloat(dec->image, p00.X, p00.Y) == DMTX_FALSE ||         dmtxImageContainsFloat(dec->image, p01.X, p01.Y) == DMTX_FALSE ||         dmtxImageContainsFloat(dec->image, p10.X, p10.Y) == DMTX_FALSE)      return DMTX_FAILURE;   dimOT = dmtxVector2Mag(dmtxVector2Sub(&vOT, &p01, &p00)); /* XXX could use MagSquared() */   dimOR = dmtxVector2Mag(dmtxVector2Sub(&vOR, &p10, &p00));   dimTX = dmtxVector2Mag(dmtxVector2Sub(&vTX, &p11, &p01));   dimRX = dmtxVector2Mag(dmtxVector2Sub(&vRX, &p11, &p10));   /* Verify that sides are reasonably long */   if(dimOT <= 8.0 || dimOR <= 8.0 || dimTX <= 8.0 || dimRX <= 8.0)      return DMTX_FAILURE;   /* Verify that the 4 corners define a reasonably fat quadrilateral */   ratio = dimOT / dimRX;   if(ratio <= 0.5 || ratio >= 2.0)      return DMTX_FAILURE;   ratio = dimOR / dimTX;   if(ratio <= 0.5 || ratio >= 2.0)      return DMTX_FAILURE;   /* Verify this is not a bowtie shape */   if(dmtxVector2Cross(&vOR, &vRX) <= 0.0 ||         dmtxVector2Cross(&vOT, &vTX) >= 0.0)      return DMTX_FAILURE;   if(RightAngleTrueness(p00, p10, p11, M_PI_2) <= dec->squareDevn)      return DMTX_FAILURE;   if(RightAngleTrueness(p10, p11, p01, M_PI_2) <= dec->squareDevn)      return DMTX_FAILURE;   /* Calculate values needed for transformations */   tx = -1 * p00.X;   ty = -1 * p00.Y;   dmtxMatrix3Translate(mtxy, tx, ty);   phi = atan2(vOT.X, vOT.Y);   dmtxMatrix3Rotate(mphi, phi);   dmtxMatrix3Multiply(m, mtxy, mphi);   dmtxMatrix3VMultiply(&vTmp, &p10, m);   shx = -vTmp.Y / vTmp.X;   dmtxMatrix3Shear(mshx, 0.0, shx);   dmtxMatrix3MultiplyBy(m, mshx);   scx = 1.0/vTmp.X;   dmtxMatrix3Scale(mscx, scx, 1.0);   dmtxMatrix3MultiplyBy(m, mscx);   dmtxMatrix3VMultiply(&vTmp, &p11, m);   scy = 1.0/vTmp.Y;   dmtxMatrix3Scale(mscy, 1.0, scy);   dmtxMatrix3MultiplyBy(m, mscy);   dmtxMatrix3VMultiply(&vTmp, &p11, m);   skx = vTmp.X;   dmtxMatrix3LineSkewSide(mskx, 1.0, skx, 1.0);   dmtxMatrix3MultiplyBy(m, mskx);   dmtxMatrix3VMultiply(&vTmp, &p01, m);   sky = vTmp.Y;   dmtxMatrix3LineSkewTop(msky, sky, 1.0, 1.0);   dmtxMatrix3Multiply(reg->raw2fit, m, msky);   /* Create inverse matrix by reverse (avoid straight matrix inversion) */   dmtxMatrix3LineSkewTopInv(msky, sky, 1.0, 1.0);   dmtxMatrix3LineSkewSideInv(mskx, 1.0, skx, 1.0);   dmtxMatrix3Multiply(m, msky, mskx);   dmtxMatrix3Scale(mscxy, 1.0/scx, 1.0/scy);   dmtxMatrix3MultiplyBy(m, mscxy);   dmtxMatrix3Shear(mshx, 0.0, -shx);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -