?? dmtxregion.c
字號:
}/** * XXX * * @param * @return XXX */static intEdgeScanNextEdge(DmtxEdgeScan *edgeScan, DmtxDecode *decode, DmtxGradient *gradient){ int pxlOffset; float lower, upper; if(edgeScan->edge.offset == edgeScan->range.lastPos) return DMTX_END_OF_RANGE; while(edgeScan->edge.offset != edgeScan->range.lastPos) { edgeScan->edge = edgeScan->edgeNext; (edgeScan->edgeNext.offset)++; // XXX pretty ugly test... should happen as part of structure with no test needed if(edgeScan->edge.offset == edgeScan->range.firstPos) { pxlOffset = dmtxImageGetOffset(&(decode->image), edgeScan->range.dir, edgeScan->range.lineNbr, edgeScan->edge.offset); dmtxColor3FromPixel(&(edgeScan->edge.color), &(decode->image.pxl[pxlOffset])); edgeScan->edge.t = dmtxDistanceAlongRay3(&(gradient->ray), &(edgeScan->edge.color)); } pxlOffset = dmtxImageGetOffset(&(decode->image), edgeScan->range.dir, edgeScan->range.lineNbr, edgeScan->edgeNext.offset); dmtxColor3FromPixel(&(edgeScan->edgeNext.color), &(decode->image.pxl[pxlOffset])); edgeScan->edgeNext.t = dmtxDistanceAlongRay3(&(gradient->ray), &(edgeScan->edgeNext.color)); // XXX This test should not be necessary, but loop boundaries are currently sketchy if(dmtxDistanceFromRay3(&(gradient->ray), &(edgeScan->edgeNext.color)) > 10.0) return DMTX_END_OF_RANGE; lower = gradient->tMid - edgeScan->edge.t; upper = gradient->tMid - edgeScan->edgeNext.t; // edge and edgeNext have the same color if(fabs(lower - upper) < DMTX_ALMOST_ZERO) { continue; } // Boundary color falls between edge and edgeNext else if(lower * upper <= 0) { edgeScan->subPixelOffset = lower / (lower - upper); if(decode && decode->crossScanCallback) (*(decode->crossScanCallback))(&(edgeScan->range), gradient, edgeScan); return DMTX_SUCCESS; } } if(decode && decode->crossScanCallback) (*(decode->crossScanCallback))(&(edgeScan->range), gradient, edgeScan); return DMTX_SUCCESS;}/** * XXX * * @param follow XXX * @param edgeScan XXX * @param gradient XXX * @param dir XXX * @return XXX */static voidEdgeFollowerInit(DmtxEdgeFollower *follow, DmtxEdgeScan *edgeScan, DmtxGradient *gradient, DmtxDirection dir){ memset(follow, 0x00, sizeof(DmtxEdgeFollower)); follow->slope = (edgeScan->edgeNext.t > edgeScan->edge.t) ? 1 : -1; follow->paraOffset = edgeScan->range.lineNbr; follow->perpOffset = edgeScan->edge.offset + edgeScan->subPixelOffset; follow->tMin = gradient->tMin; follow->tMid = gradient->tMid; follow->tMax = gradient->tMax; follow->ray = gradient->ray; follow->dir = dir;}/** * XXX * * @param follow XXX * @return XXX */static DmtxVector2EdgeFollowerGetLoc(DmtxEdgeFollower *follow){ DmtxVector2 loc; if(follow->dir & DmtxDirVertical) { loc.X = follow->perpOffset; loc.Y = follow->paraOffset; } else { loc.X = follow->paraOffset; loc.Y = follow->perpOffset; } return loc;}/** * XXX * * @param follow XXX * @param decode XXX * @return XXX */static intEdgeFollowerFollow(DmtxEdgeFollower *follow, DmtxDecode *decode){ // initialize line0 and line1 to "unset" and zero strength int i; int anchorStrength = 0; float offPath, offAngle; DmtxVector2 vTmp, anchorStep, fStep[DMTX_FOLLOW_STEPS]; DmtxRay2 rayAnchor, rayNext; memset(&(follow->line0), 0x00, sizeof(DmtxRay2)); memset(&(follow->line1), 0x00, sizeof(DmtxRay2)); // Build first vector by incrementing 5 steps anchorStep = fStep[0] = EdgeFollowerGetLoc(follow); for(i = 1; i < DMTX_FOLLOW_STEPS; i++) { if(EdgeFollowerIncrement(follow, decode) != DMTX_EDGE_FOUND) { if(decode && decode->plotPointCallback) (*(decode->plotPointCallback))(EdgeFollowerGetLoc(follow), 1, 2, DMTX_DISPLAY_SQUARE); return 0; // Lost edge before completing first vector } fStep[i] = EdgeFollowerGetLoc(follow); } dmtxVector2Sub(&vTmp, &(fStep[DMTX_FOLLOW_STEPS-1]), &(fStep[0])); dmtxVector2Norm(&vTmp); // XXX potential problem here if follower ends up in starting point (div/0) rayAnchor.p = fStep[0]; rayAnchor.v = vTmp; // Continue while we can still find an edge while(EdgeFollowerIncrement(follow, decode) == DMTX_EDGE_FOUND) { if(follow->turnCount > 2) { // Reached maximum number of turns if(decode && decode->plotPointCallback) // Plot a red X where edge was lost (*(decode->plotPointCallback))(fStep[0], 1, 2, DMTX_DISPLAY_SQUARE); return 0; // XXX this should probably reflect the edge status (e.g. lost, max_turns, etc...) } // incrementProgress(follow, anchorVector); (using current followVector) for(i = 0; i < DMTX_FOLLOW_STEPS - 1; i++) { fStep[i] = fStep[i+1]; // XXX innefficient, but simple } fStep[i] = EdgeFollowerGetLoc(follow); dmtxVector2Sub(&vTmp, &(fStep[DMTX_FOLLOW_STEPS-1]), &(fStep[0])); dmtxVector2Norm(&vTmp); rayNext.p = fStep[0]; rayNext.v = vTmp; offPath = fabs(dmtxDistanceFromRay2(&rayAnchor, &(fStep[0]))); offAngle = fabs(dmtxVector2Dot(&(rayAnchor.v), &(rayNext.v))); // Step is in direction of predicted path if(offAngle > 0.984) { anchorStrength++; } else { // Step is in wrong direction // Current line is done -- fixate if(anchorStrength > 10) { // if line reached strength threshhold, but is now turning a corner // line0 gets set first if(follow->line0.isDefined == 0) { if(decode && decode->plotPointCallback) (*(decode->plotPointCallback))(fStep[0], 2, 2, DMTX_DISPLAY_SQUARE); // Update should build ray based on min/max points on the edge, NOT anchorVector // XXXXXXXXX IMPORTANT: Revisit this... results should be adequate using anchorVector here follow->line0.isDefined = 1; dmtxVector2Sub(&vTmp, &(fStep[0]), &anchorStep); dmtxVector2Norm(&vTmp); follow->line0.v = vTmp; follow->line0.p = anchorStep; follow->line0.tMin = 0; follow->line0.tMax = dmtxDistanceAlongRay2(&(follow->line0), &(fStep[0])); } // line1 gets set if line0 is already set else { if(decode && decode->plotPointCallback) (*(decode->plotPointCallback))(fStep[0], 3, 2, DMTX_DISPLAY_SQUARE); // Update should build ray based on min/max points on the edge, NOT anchorVector // XXXXXXXXX IMPORTANT: Revisit this... results should be adequate using anchorVector here follow->line1.isDefined = 1; dmtxVector2Sub(&vTmp, &(fStep[0]), &anchorStep); dmtxVector2Norm(&vTmp); follow->line1.v = vTmp; follow->line1.p = anchorStep; follow->line1.tMin = 0; follow->line1.tMax = dmtxDistanceAlongRay2(&(follow->line1), &(fStep[0])); return 0; // return "full" } } else { // line never reached strength threshhold if(decode && decode->plotPointCallback) (*(decode->plotPointCallback))(fStep[0], 4, 2, DMTX_DISPLAY_SQUARE); } rayAnchor = rayNext; anchorStep = fStep[0]; anchorStrength = 0; } } // return edge_lost condition (range/right/left) if(decode && decode->plotPointCallback) (*(decode->plotPointCallback))(EdgeFollowerGetLoc(follow), 5, 2, DMTX_DISPLAY_SQUARE); return 0;}/** * XXX * * @param * @return XXX */static intEdgeFollowerIncrement(DmtxEdgeFollower *follow, DmtxDecode *decode){ int turnDir; int increment; int offset0, offset1, endOffset; int dir; float t0, t1; float tmpOffset; DmtxColor3 color0, color1; // XXX this first calc of offset0 might be done smarter by extrapolating current "line" offset0 = (int)(follow->perpOffset + 0.5); if(((follow->dir & DmtxDirHorizontal) && (offset0 + 1 >= decode->image.height - 1)) || ((follow->dir & DmtxDirVertical) && (offset0 + 1 >= decode->image.width - 1)) || offset0 - 1 <= 0) return DMTX_END_OF_RANGE; increment = (follow->dir & DmtxDirRightUp) ? 1 : -1; follow->paraOffset += increment; if(((follow->dir & DmtxDirHorizontal) && (follow->paraOffset >= decode->image.width)) || ((follow->dir & DmtxDirVertical) && (follow->paraOffset >= decode->image.height)) || follow->paraOffset <= 0) return DMTX_END_OF_RANGE; if(follow->dir & DmtxDirVertical) dmtxColor3FromPixel(&color0, &(decode->image.pxl[decode->image.width * follow->paraOffset + offset0])); else dmtxColor3FromPixel(&color0, &(decode->image.pxl[decode->image.width * offset0 + follow->paraOffset])); t0 = dmtxDistanceAlongRay3(&(follow->ray), &color0); dir = (follow->slope * (follow->tMid - t0) >= 0) ? 1 : -1; // Find adjacent pixels whose values "surround" tMid endOffset = offset0 + 3*dir; for(offset1 = offset0; offset1 != endOffset; offset1 += dir) { if(((follow->dir & DmtxDirHorizontal) && (offset1 + 1 >= decode->image.height - 1)) || ((follow->dir & DmtxDirVertical) && (offset1 + 1 >= decode->image.width - 1)) || offset1 - 1 <= 0) return DMTX_END_OF_RANGE; if(follow->dir & DmtxDirVertical) dmtxColor3FromPixel(&color1, &(decode->image.pxl[decode->image.width * follow->paraOffset + offset1])); else dmtxColor3FromPixel(&color1, &(decode->image.pxl[decode->image.width * offset1 + follow->paraOffset])); t1 = dmtxDistanceAlongRay3(&(follow->ray), &color1); // Check that follower hasn't wandered off of edge following unlike colors if(dmtxDistanceFromRay3(&(follow->ray), &color1) > DMTX_MAX_COLOR_DEVN) { return DMTX_END_OF_RANGE; // XXX not really DMTX_END_OF_RANGE, but works for now } if(fabs(t1 - follow->tMid) < DMTX_ALMOST_ZERO || ((follow->tMid - t0) * (follow->tMid - t1) < 0)) { if(fabs(t1 - follow->tMid) < DMTX_ALMOST_ZERO) { follow->perpOffset = offset1; } else if(fabs(follow->tMid - t0) < fabs(follow->tMid - t1)) { follow->perpOffset = offset0 + follow->slope * ((follow->tMid - t0)/fabs(t0 - t1)); } else { follow->perpOffset = offset1 + follow->slope * ((follow->tMid - t1)/fabs(t0 - t1)); } if(decode && decode->followScanCallback) (*(decode->followScanCallback))(follow); return DMTX_EDGE_FOUND; } else { offset0 = offset1; t0 = t1; } } tmpOffset = follow->paraOffset; follow->paraOffset = follow->perpOffset; follow->perpOffset = tmpOffset; if(follow->dir & (DmtxDirUp | DmtxDirLeft)) turnDir = (dir > 0) ? DMTX_TURN_CW : DMTX_TURN_CCW; else turnDir = (dir > 0) ? DMTX_TURN_CCW : DMTX_TURN_CW; // XXX Whoa, this one was hard to figure out if(follow->dir & DmtxDirVertical && turnDir == DMTX_TURN_CW) follow->slope *= -1; else if(follow->dir & DmtxDirHorizontal && turnDir == DMTX_TURN_CCW) follow->slope *= -1; follow->turnCount++; follow->dir = TurnCorner(follow->dir, turnDir); return DMTX_EDGE_FOUND;}/** * XXX * * @param * @return XXX */static voidMatrixRegionInit(DmtxMatrixRegion *matrixRegion, DmtxGradient *gradient){ memset(matrixRegion, 0x00, sizeof(DmtxMatrixRegion)); matrixRegion->gradient = *gradient; // XXX this stuff just became a lot less important since I'm initializing it locally in "chain" and then copying matrixRegion->chain.tx = 0.0; matrixRegion->chain.ty = 0.0; matrixRegion->chain.phi = 0.0; matrixRegion->chain.shx = 0.0; matrixRegion->chain.scx = 1.0; matrixRegion->chain.scy = 1.0; matrixRegion->chain.bx0 = 100.0;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -