📄 dmtxregion.c
字号:
{ int i; int sign; int offset; DmtxFollow follow; follow.loc = reg->flowBegin.loc; offset = dmtxImageGetOffset(dec->image, follow.loc.X, follow.loc.Y); assert(offset != DMTX_BAD_OFFSET); follow.step = 0; follow.ptr = &(dec->image->cache[offset]); follow.neighbor = *follow.ptr; sign = (seek > 0) ? +1 : -1; for(i = 0; i != seek; i += sign) { follow = FollowStep(dec, reg, follow, sign); assert(follow.ptr != NULL); assert(abs(follow.step) <= reg->stepsTotal); } return follow;}/** * * */static DmtxFollowFollowSeekLoc(DmtxDecode *dec, DmtxPixelLoc loc){ int offset; DmtxFollow follow; follow.loc = loc; offset = dmtxImageGetOffset(dec->image, follow.loc.X, follow.loc.Y); assert(offset != DMTX_BAD_OFFSET); follow.step = 0; follow.ptr = &(dec->image->cache[offset]); follow.neighbor = *follow.ptr; return follow;}/** * * */static DmtxFollowFollowStep(DmtxDecode *dec, DmtxRegion *reg, DmtxFollow followBeg, int sign){ int offset; int patternIdx; int stepMod; int factor; DmtxFollow follow; assert(abs(sign) == 1); assert((int)(followBeg.neighbor & 0x40) != 0x00); factor = reg->stepsTotal + 1; if(sign > 0) stepMod = (factor + (followBeg.step % factor)) % factor; else stepMod = (factor - (followBeg.step % factor)) % factor; /* End of positive trail -- magic jump */ if(sign > 0 && stepMod == reg->jumpToNeg) { follow.loc = reg->finalNeg; } /* End of negative trail -- magic jump */ else if(sign < 0 && stepMod == reg->jumpToPos) { follow.loc = reg->finalPos; } /* Trail in progress -- normal jump */ else { patternIdx = (sign < 0) ? followBeg.neighbor & 0x07 : ((followBeg.neighbor & 0x38) >> 3); follow.loc.X = followBeg.loc.X + dmtxPatternX[patternIdx]; follow.loc.Y = followBeg.loc.Y + dmtxPatternY[patternIdx]; follow.loc.status = DMTX_RANGE_GOOD; } offset = dmtxImageGetOffset(dec->image, follow.loc.X, follow.loc.Y); assert(offset != DMTX_BAD_OFFSET); follow.step = followBeg.step + sign; follow.ptr = &(dec->image->cache[offset]); follow.neighbor = *follow.ptr; return follow;}/** * * */static DmtxFollowFollowStep2(DmtxDecode *dec, DmtxRegion *reg, DmtxFollow followBeg, int sign){ int offset; int patternIdx; DmtxFollow follow; assert(abs(sign) == 1); assert((int)(followBeg.neighbor & 0x40) != 0x00); patternIdx = (sign < 0) ? followBeg.neighbor & 0x07 : ((followBeg.neighbor & 0x38) >> 3); follow.loc.X = followBeg.loc.X + dmtxPatternX[patternIdx]; follow.loc.Y = followBeg.loc.Y + dmtxPatternY[patternIdx]; follow.loc.status = DMTX_RANGE_GOOD; offset = dmtxImageGetOffset(dec->image, follow.loc.X, follow.loc.Y); assert(offset != DMTX_BAD_OFFSET); follow.step = followBeg.step + sign; follow.ptr = &(dec->image->cache[offset]); follow.neighbor = *follow.ptr; return follow;}/** * vaiiiooo * -------- * 0x80 v = visited bit * 0x40 a = assigned bit * 0x38 u = 3 bits points upstream 0-7 * 0x07 d = 3 bits points downstream 0-7 */static intTrailBlazeContinuous(DmtxDecode *dec, DmtxRegion *reg, DmtxPointFlow flowBegin, int maxDiagonal){ int posAssigns, negAssigns, clears; int sign; int steps; int offset; unsigned char *cache, *cacheNext, *cacheBeg; DmtxPointFlow flow, flowNext; DmtxPixelLoc boundMin, boundMax; /* check offset before starting */ offset = dmtxImageGetOffset(dec->image, flowBegin.loc.X, flowBegin.loc.Y); if(offset == DMTX_BAD_OFFSET) return DMTX_FAILURE; boundMin = boundMax = flowBegin.loc; cacheBeg = &(dec->image->cache[offset]); *cacheBeg = (0x80 | 0x40); /* Mark location as visited and assigned */ reg->flowBegin = flowBegin; posAssigns = negAssigns = 0; for(sign = 1; sign >= -1; sign -= 2) { flow = flowBegin; cache = cacheBeg; for(steps = 0; ; steps++) { if(maxDiagonal != -1 && (boundMax.X - boundMin.X > maxDiagonal || boundMax.Y - boundMin.Y > maxDiagonal)) break; /* Find the strongest eligible neighbor */ flowNext = FindStrongestNeighbor(dec, flow, sign); if(flowNext.mag < 50) break; offset = dmtxImageGetOffset(dec->image, flowNext.loc.X, flowNext.loc.Y); if(offset == DMTX_BAD_OFFSET) break; /* Get the neighbor's cache location */ cacheNext = &(dec->image->cache[offset]); assert(!(*cacheNext & 0x80)); /* Mark departure from current location. If flowing downstream * (sign < 0) then departure vector here is the arrival vector * of the next location. Upstream flow uses the opposite rule. */ *cache |= (sign < 0) ? flowNext.arrive : flowNext.arrive << 3; /* Mark known direction for next location */ /* If testing downstream (sign < 0) then next upstream is opposite of next arrival */ /* If testing upstream (sign > 0) then next downstream is opposite of next arrival */ *cacheNext = (sign < 0) ? (((flowNext.arrive + 4)%8) << 3) : ((flowNext.arrive + 4)%8); *cacheNext |= (0x80 | 0x40); /* Mark location as visited and assigned */ if(sign > 0) posAssigns++; else negAssigns++; cache = cacheNext; flow = flowNext; if(flow.loc.X > boundMax.X) boundMax.X = flow.loc.X; else if(flow.loc.X < boundMin.X) boundMin.X = flow.loc.X; if(flow.loc.Y > boundMax.Y) boundMax.Y = flow.loc.Y; else if(flow.loc.Y < boundMin.Y) boundMin.Y = flow.loc.Y;/* CALLBACK_POINT_PLOT(flow.loc, (sign > 0) ? 2 : 3, 1, DMTX_DISPLAY_POINT); */ } if(sign > 0) { reg->finalPos = flow.loc; reg->jumpToNeg = steps; } else { reg->finalNeg = flow.loc; reg->jumpToPos = steps; } } reg->stepsTotal = reg->jumpToPos + reg->jumpToNeg; reg->boundMin = boundMin; reg->boundMax = boundMax; /* Clear "visited" bit from trail */ clears = TrailClear(dec, reg, 0x80); assert(posAssigns + negAssigns == clears - 1); /* XXX clean this up ... redundant test above */ if(maxDiagonal != -1 && (boundMax.X - boundMin.X > maxDiagonal || boundMax.Y - boundMin.Y > maxDiagonal)) return DMTX_FAILURE; return DMTX_SUCCESS;}/** * recives bresline, and follows strongest neighbor unless it involves * ratcheting bresline inward or backward (although back + outward is allowed). * */static intTrailBlazeGapped(DmtxDecode *dec, DmtxRegion *reg, DmtxBresLine line, int streamDir){ unsigned char *beforeCache, *afterCache; int err; int onEdge; int distSq, distSqMax; int travel, outward; int xDiff, yDiff; int steps; int stepDir, dirMap[] = { 0, 1, 2, 7, 8, 3, 6, 5, 4 }; DmtxPixelLoc beforeStep, afterStep; DmtxPointFlow flow, flowNext; DmtxPixelLoc loc0; int xStep, yStep; loc0 = line.loc; flow = GetPointFlow(dec, reg->flowBegin.plane, loc0, dmtxNeighborNone); distSqMax = (line.xDelta * line.xDelta) + (line.yDelta * line.yDelta); steps = 0; onEdge = 1; beforeStep = loc0; beforeCache = GetCacheAddress(dec, loc0.X, loc0.Y); if(beforeCache == NULL) return DMTX_FAILURE; else *beforeCache = 0x00; /* probably should just overwrite one direction */ do { if(onEdge != 0) { flowNext = FindStrongestNeighbor(dec, flow, streamDir); if(flowNext.mag == -1) break; err = BresLineGetStep(line, flowNext.loc, &travel, &outward); if(flowNext.mag < 50 || outward < 0 || (outward == 0 && travel < 0)) { onEdge = 0; } else { BresLineStep(&line, travel, outward); flow = flowNext; } } if(!onEdge) { BresLineStep(&line, 1, 0); flow = GetPointFlow(dec, reg->flowBegin.plane, line.loc, dmtxNeighborNone); if(flow.mag > 50) onEdge = 1; } afterStep = line.loc; afterCache = GetCacheAddress(dec, afterStep.X, afterStep.Y); if(afterCache == NULL) break; /* Determine step direction using pure magic */ xStep = afterStep.X - beforeStep.X; yStep = afterStep.Y - beforeStep.Y; assert(abs(xStep) <= 1 && abs(yStep) <= 1); stepDir = dirMap[3 * yStep + xStep + 4]; assert(stepDir != 8); if(streamDir < 0) { *beforeCache |= (0x40 | stepDir); *afterCache = (((stepDir + 4)%8) << 3); } else { *beforeCache |= (0x40 | (stepDir << 3)); *afterCache = ((stepDir + 4)%8); } /* Guaranteed to have taken one step since top of loop */ xDiff = line.loc.X - loc0.X; yDiff = line.loc.Y - loc0.Y; distSq = (xDiff * xDiff) + (yDiff * yDiff); beforeStep = line.loc; beforeCache = afterCache; steps++; } while(distSq < distSqMax); return steps;}/** * * */static intTrailClear(DmtxDecode *dec, DmtxRegion *reg, int clearMask){ int clears; DmtxFollow follow; assert((clearMask | 0xff) == 0xff); /* Clear "visited" bit from trail */ clears = 0; follow = FollowSeek(dec, reg, 0); while(abs(follow.step) <= reg->stepsTotal) { assert((int)(*follow.ptr & clearMask) != 0x00); *follow.ptr &= (clearMask ^ 0xff); follow = FollowStep(dec, reg, follow, +1); clears++; } return clears;}/** * * */static DmtxBestLineFindBestSolidLine(DmtxDecode *dec, DmtxRegion *reg, int step0, int step1, int streamDir, int houghAvoid){ int hough[3][DMTX_HOUGH_RES] = { { 0 } }; int houghMin, houghMax; char houghTest[DMTX_HOUGH_RES]; int i; int step; int sign; int tripSteps; int angleBest; int hOffset, hOffsetBest; int xDiff, yDiff; int dH; DmtxRay2 rH; DmtxFollow follow; DmtxBestLine line; DmtxPixelLoc rHp; memset(&line, 0x00, sizeof(DmtxBestLine)); memset(&rH, 0x00, sizeof(DmtxRay2)); angleBest = 0; hOffset = hOffsetBest = 0; /* Always follow path flowing away from the trail start */ if(step0 != 0) { if(step0 > 0) { sign = +1; tripSteps = (step1 - step0 + reg->stepsTotal) % reg->stepsTotal; } else { sign = -1; tripSteps = (step0 - step1 + reg->stepsTotal) % reg->stepsTotal; } if(tripSteps == 0) tripSteps = reg->stepsTotal; } else if(step1 != 0) { sign = (step1 > 0) ? +1 : -1; tripSteps = abs(step1); } else if(step1 == 0) { sign = +1; tripSteps = reg->stepsTotal; } assert(sign == streamDir); follow = FollowSeek(dec, reg, step0); rHp = follow.loc; line.stepBeg = line.stepPos = line.stepNeg = step0; line.locBeg = follow.loc; line.locPos = follow.loc; line.locNeg = follow.loc; /* Predetermine which angles to test */ for(i = 0; i < DMTX_HOUGH_RES; i++) { if(houghAvoid == -1) { houghTest[i] = 1; } else { houghMin = (houghAvoid + DMTX_HOUGH_RES/6) % DMTX_HOUGH_RES; houghMax = (houghAvoid - DMTX_HOUGH_RES/6 + DMTX_HOUGH_RES) % DMTX_HOUGH_RES; if(houghMin > houghMax) houghTest[i] = (i > houghMin || i < houghMax) ? 1 : 0; else houghTest[i] = (i > houghMin && i < houghMax) ? 1 : 0; } } /* Test each angle for steps along path */ for(step = 0; step < tripSteps; step++) { xDiff = follow.loc.X - rHp.X; yDiff = follow.loc.Y - rHp.Y; /* Increment Hough accumulator */ for(i = 0; i < DMTX_HOUGH_RES; i++) { if((int)houghTest[i] == 0) continue; dH = (rHvX[i] * yDiff) - (rHvY[i] * xDiff); if(dH >= -384 && dH <= 384) { if(dH > 128) hOffset = 2; else if(dH >= -128) hOffset = 1; else hOffset = 0; hough[hOffset][i]++; /* New angle takes over lead */ if(hough[hOffset][i] > hough[hOffsetBest][angleBest]) { angleBest = i; hOffsetBest = hOffset; } } }/* CALLBACK_POINT_PLOT(follow.loc, (sign > 1) ? 4 : 3, 1, DMTX_DISPLAY_POINT); */ follow = FollowStep(dec, reg, follow, sign); } line.angle = angleBest; line.hOffset = hOffsetBest; line.mag = hough[hOffsetBest][angleBest]; return line;}/** * * */static DmtxBestLineFindBestSolidLine2(DmtxDecode *dec, DmtxRegion *reg, DmtxPixelLoc loc0, int tripSteps, int sign, int houghAvoid){ int hough[3][DMTX_HOUGH_RES] = { { 0 } }; int houghMin, houghMax; char houghTest[DMTX_HOUGH_RES]; int i; int step; int angleBest; int hOffset, hOffsetBest; int xDiff, yDiff; int dH; DmtxRay2 rH; DmtxBestLine line; DmtxPixelLoc rHp; DmtxFollow follow; memset(&line, 0x00, sizeof(DmtxBestLine)); memset(&rH, 0x00, sizeof(DmtxRay2));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -