Example #1
0
 internal DmtxRegion(DmtxRegion src)
 {
     this._bottomAngle = src._bottomAngle;
     this._bottomKnown = src._bottomKnown;
     this._bottomLine  = src._bottomLine;
     this._bottomLoc   = src._bottomLoc;
     this._boundMax    = src._boundMax;
     this._boundMin    = src._boundMin;
     this._finalNeg    = src._finalNeg;
     this._finalPos    = src._finalPos;
     this._fit2raw     = new DmtxMatrix3(src._fit2raw);
     this._flowBegin   = src._flowBegin;
     this._jumpToNeg   = src._jumpToNeg;
     this._jumpToPos   = src._jumpToPos;
     this._leftAngle   = src._leftAngle;
     this._leftKnown   = src._leftKnown;
     this._leftLine    = src._leftLine;
     this._leftLoc     = src._leftLoc;
     this._locR        = src._locR;
     this._locT        = src._locT;
     this._mappingCols = src._mappingCols;
     this._mappingRows = src._mappingRows;
     this._offColor    = src._offColor;
     this._onColor     = src._onColor;
     this._polarity    = src._polarity;
     this._raw2fit     = new DmtxMatrix3(src._raw2fit);
     this._rightAngle  = src._rightAngle;
     this._rightKnown  = src._rightKnown;
     this._rightLoc    = src._rightLoc;
     this._sizeIdx     = src._sizeIdx;
     this._stepR       = src._stepR;
     this._stepsTotal  = src._stepsTotal;
     this._stepT       = src._stepT;
     this._symbolCols  = src._symbolCols;
     this._symbolRows  = src._symbolRows;
     this._topAngle    = src._topAngle;
     this._topKnown    = src._topKnown;
     this._topLoc      = src._topLoc;
 }
Example #2
0
 internal DmtxRegion(DmtxRegion src)
 {
     this._bottomAngle = src._bottomAngle;
     this._bottomKnown = src._bottomKnown;
     this._bottomLine = src._bottomLine;
     this._bottomLoc = src._bottomLoc;
     this._boundMax = src._boundMax;
     this._boundMin = src._boundMin;
     this._finalNeg = src._finalNeg;
     this._finalPos = src._finalPos;
     this._fit2raw = new DmtxMatrix3(src._fit2raw);
     this._flowBegin = src._flowBegin;
     this._jumpToNeg = src._jumpToNeg;
     this._jumpToPos = src._jumpToPos;
     this._leftAngle = src._leftAngle;
     this._leftKnown = src._leftKnown;
     this._leftLine = src._leftLine;
     this._leftLoc = src._leftLoc;
     this._locR = src._locR;
     this._locT = src._locT;
     this._mappingCols = src._mappingCols;
     this._mappingRows = src._mappingRows;
     this._offColor = src._offColor;
     this._onColor = src._onColor;
     this._polarity = src._polarity;
     this._raw2fit = new DmtxMatrix3(src._raw2fit);
     this._rightAngle = src._rightAngle;
     this._rightKnown = src._rightKnown;
     this._rightLoc = src._rightLoc;
     this._sizeIdx = src._sizeIdx;
     this._stepR = src._stepR;
     this._stepsTotal = src._stepsTotal;
     this._stepT = src._stepT;
     this._symbolCols = src._symbolCols;
     this._symbolRows = src._symbolRows;
     this._topAngle = src._topAngle;
     this._topKnown = src._topKnown;
     this._topLoc = src._topLoc;
 }
Example #3
0
        DmtxPointFlow FindStrongestNeighbor(DmtxPointFlow center, int sign)
        {
            int i;
            int strongIdx;
            int attempt, attemptDiff;
            int occupied;
            DmtxPixelLoc loc = new DmtxPixelLoc();
            DmtxPointFlow[] flow = new DmtxPointFlow[8];

            attempt = (sign < 0) ? center.Depart : (center.Depart + 4) % 8;

            occupied = 0;
            strongIdx = DmtxConstants.DmtxUndefined;
            for (i = 0; i < 8; i++)
            {

                loc.X = center.Loc.X + DmtxConstants.DmtxPatternX[i];
                loc.Y = center.Loc.Y + DmtxConstants.DmtxPatternY[i];
                int cacheIndex = DecodeGetCache(loc.X, loc.Y);
                if (cacheIndex == DmtxConstants.DmtxUndefined)
                {
                    continue;
                }

                if ((int)(this._cache[cacheIndex] & 0x80) != 0x00)
                {
                    if (++occupied > 2)
                        return DmtxConstants.DmtxBlankEdge;
                    else
                        continue;
                }

                attemptDiff = Math.Abs(attempt - i);
                if (attemptDiff > 4)
                    attemptDiff = 8 - attemptDiff;
                if (attemptDiff > 1)
                    continue;

                flow[i] = GetPointFlow(center.Plane, loc, i);

                if (strongIdx == DmtxConstants.DmtxUndefined || flow[i].Mag > flow[strongIdx].Mag ||
                      (flow[i].Mag == flow[strongIdx].Mag && ((i & 0x01) != 0)))
                {
                    strongIdx = i;
                }
            }

            return (strongIdx == DmtxConstants.DmtxUndefined) ? DmtxConstants.DmtxBlankEdge : flow[strongIdx];
        }
Example #4
0
        bool TrailBlazeContinuous(DmtxRegion reg, DmtxPointFlow flowBegin, int maxDiagonal)
        {
            int posAssigns, negAssigns, clears;
            int sign;
            int steps;
            DmtxPointFlow flow, flowNext;
            DmtxPixelLoc boundMin, boundMax;

            boundMin = boundMax = flowBegin.Loc;
            int cacheBegIndex = DecodeGetCache(flowBegin.Loc.X, flowBegin.Loc.Y);
            this._cache[cacheBegIndex] = 0x80 | 0x40;

            reg.FlowBegin = flowBegin;

            posAssigns = negAssigns = 0;
            for (sign = 1; sign >= -1; sign -= 2)
            {

                flow = flowBegin;
                int cacheIndex = cacheBegIndex;

                for (steps = 0; ; steps++)
                {

                    if (maxDiagonal != DmtxConstants.DmtxUndefined && (boundMax.X - boundMin.X > maxDiagonal ||
                          boundMax.Y - boundMin.Y > maxDiagonal))
                        break;

                    /* Find the strongest eligible neighbor */
                    flowNext = FindStrongestNeighbor(flow, sign);
                    if (flowNext.Mag < 50)
                        break;

                    /* Get the neighbor's cache location */
                    int cacheNextIndex = DecodeGetCache(flowNext.Loc.X, flowNext.Loc.Y);
                    if ((this._cache[cacheNextIndex] & 0x80) != 0)
                    {
                        throw new Exception("Error creating Trail Blaze");
                    }

                    /* 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. */
                    this._cache[cacheIndex] |= (sign < 0) ? (byte)(flowNext.Arrive) : (byte)(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 */
                    this._cache[cacheNextIndex] = (sign < 0) ? (byte)(((flowNext.Arrive + 4) % 8) << 3) : (byte)((flowNext.Arrive + 4) % 8);
                    this._cache[cacheNextIndex] |= (0x80 | 0x40); /* Mark location as visited and assigned */

                    if (sign > 0)
                        posAssigns++;
                    else
                        negAssigns++;
                    cacheIndex = cacheNextIndex;
                    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, 2); */
                }

                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(reg, 0x80);
            if (!(posAssigns + negAssigns == clears - 1))
            {
                throw new Exception("Error cleaning after trail blaze continuous");
            }

            /* XXX clean this up ... redundant test above */
            if (maxDiagonal != DmtxConstants.DmtxUndefined && (boundMax.X - boundMin.X > maxDiagonal ||
                  boundMax.Y - boundMin.Y > maxDiagonal))
                return false;

            return true;
        }
Example #5
0
        DmtxPointFlow MatrixRegionSeekEdge(DmtxPixelLoc loc)
        {
            DmtxPointFlow flow;
            DmtxPointFlow[] flowPlane = new DmtxPointFlow[3];
            DmtxPointFlow flowPos, flowPosBack;
            DmtxPointFlow flowNeg, flowNegBack;

            int channelCount = _image.ChannelCount;

            /* Find whether red, green, or blue shows the strongest edge */
            int strongIdx = 0;
            for (int i = 0; i < channelCount; i++)
            {
                flowPlane[i] = GetPointFlow(i, loc, DmtxConstants.DmtxNeighborNone);
                if (i > 0 && flowPlane[i].Mag > flowPlane[strongIdx].Mag)
                    strongIdx = i;
            }

            if (flowPlane[strongIdx].Mag < 10)
                return DmtxConstants.DmtxBlankEdge;

            flow = flowPlane[strongIdx];

            flowPos = FindStrongestNeighbor(flow, +1);
            flowNeg = FindStrongestNeighbor(flow, -1);
            if (flowPos.Mag != 0 && flowNeg.Mag != 0)
            {
                flowPosBack = FindStrongestNeighbor(flowPos, -1);
                flowNegBack = FindStrongestNeighbor(flowNeg, +1);
                if (flowPos.Arrive == (flowPosBack.Arrive + 4) % 8 &&
                      flowNeg.Arrive == (flowNegBack.Arrive + 4) % 8)
                {
                    flow.Arrive = DmtxConstants.DmtxNeighborNone;
                    //CALLBACK_POINT_PLOT(flow.Loc, 1, 1, 1);
                    return flow;
                }
            }

            return DmtxConstants.DmtxBlankEdge;
        }
Example #6
0
        bool MatrixRegionOrientation(DmtxRegion reg, DmtxPointFlow begin)
        {
            int cross;
            int minArea;
            int scale;
            DmtxSymbolSize symbolShape;
            int maxDiagonal;
            bool err;
            DmtxBestLine line1x, line2x;
            DmtxBestLine line2n, line2p;
            DmtxFollow fTmp;

            if (this._sizeIdxExpected == DmtxSymbolSize.DmtxSymbolSquareAuto ||
                  (this._sizeIdxExpected >= DmtxSymbolSize.DmtxSymbol10x10 &&
                  this._sizeIdxExpected <= DmtxSymbolSize.DmtxSymbol144x144))
                symbolShape = DmtxSymbolSize.DmtxSymbolSquareAuto;
            else if (this._sizeIdxExpected == DmtxSymbolSize.DmtxSymbolRectAuto ||
                  (this._sizeIdxExpected >= DmtxSymbolSize.DmtxSymbol8x18 &&
                  this._sizeIdxExpected <= DmtxSymbolSize.DmtxSymbol16x48))
                symbolShape = DmtxSymbolSize.DmtxSymbolRectAuto;
            else
                symbolShape = DmtxSymbolSize.DmtxSymbolShapeAuto;

            if (_edgeMax != DmtxConstants.DmtxUndefined)
            {
                if (symbolShape == DmtxSymbolSize.DmtxSymbolRectAuto)
                    maxDiagonal = (int)(1.23 * _edgeMax + 0.5); /* sqrt(5/4) + 10% */
                else
                    maxDiagonal = (int)(1.56 * _edgeMax + 0.5); /* sqrt(2) + 10% */
            }
            else
            {
                maxDiagonal = DmtxConstants.DmtxUndefined;
            }

            /* Follow to end in both directions */
            err = TrailBlazeContinuous(reg, begin, maxDiagonal);
            if (err == false || reg.StepsTotal < 40)
            {
                TrailClear(reg, 0x40);
                return false;
            }

            /* Filter out region candidates that are smaller than expected */
            if (this._edgeMin != DmtxConstants.DmtxUndefined)
            {
                scale = _scale;

                if (symbolShape == DmtxSymbolSize.DmtxSymbolSquareAuto)
                    minArea = (this._edgeMin * this._edgeMin) / (scale * scale);
                else
                    minArea = (2 * this._edgeMin * this._edgeMin) / (scale * scale);

                if ((reg.BoundMax.X - reg.BoundMin.X) * (reg.BoundMax.Y - reg.BoundMin.Y) < minArea)
                {
                    TrailClear(reg, 0x40);
                    return false;
                }
            }

            line1x = FindBestSolidLine(reg, 0, 0, 1, DmtxConstants.DmtxUndefined);
            if (line1x.Mag < 5)
            {
                TrailClear(reg, 0x40);
                return false;
            }

            err = FindTravelLimits(reg, ref line1x);
            if (line1x.DistSq < 100 || line1x.Devn * 10 >= Math.Sqrt((double)line1x.DistSq))
            {
                TrailClear(reg, 0x40);
                return false;
            }
            if (!(line1x.StepPos >= line1x.StepNeg))
            {
                throw new Exception("Error calculating matrix region orientation");
            }

            fTmp = FollowSeek(reg, line1x.StepPos + 5);
            line2p = FindBestSolidLine(reg, fTmp.Step, line1x.StepNeg, 1, line1x.Angle);

            fTmp = FollowSeek(reg, line1x.StepNeg - 5);
            line2n = FindBestSolidLine(reg, fTmp.Step, line1x.StepPos, -1, line1x.Angle);
            if (DmtxCommon.Max<int>(line2p.Mag, line2n.Mag) < 5)
                return false;

            if (line2p.Mag > line2n.Mag)
            {
                line2x = line2p;
                err = FindTravelLimits(reg, ref line2x);
                if (line2x.DistSq < 100 || line2x.Devn * 10 >= Math.Sqrt((double)line2x.DistSq))
                    return false;

                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(reg, ref line2x);
                if (line2x.DistSq < 100 || line2x.Devn / Math.Sqrt((double)line2x.DistSq) >= 0.1)
                    return false;

                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;
                }
            }

            reg.LeftKnown = reg.BottomKnown = 1;

            return true;
        }
Example #7
0
        DmtxPointFlow GetPointFlow(int colorPlane, DmtxPixelLoc loc, int arrive)
        {
            int[] coefficient = new int[] { 0, 1, 2, 1, 0, -1, -2, -1 };
            bool err;
            int patternIdx, coefficientIdx;
            int compass, compassMax;
            int[] mag = new int[4];
            int xAdjust, yAdjust;
            int color;
            int[] colorPattern = new int[8];
            DmtxPointFlow flow = new DmtxPointFlow();

            for (patternIdx = 0; patternIdx < 8; patternIdx++)
            {
                xAdjust = loc.X + DmtxConstants.DmtxPatternX[patternIdx];
                yAdjust = loc.Y + DmtxConstants.DmtxPatternY[patternIdx];
                err = GetPixelValue(xAdjust, yAdjust, colorPlane, ref colorPattern[patternIdx]);
                if (err == false)
                {
                    return DmtxConstants.DmtxBlankEdge;
                }
            }

            /* Calculate this pixel's flow intensity for each direction (-45, 0, 45, 90) */
            compassMax = 0;
            for (compass = 0; compass < 4; compass++)
            {

                /* Add portion from each position in the convolution matrix pattern */
                for (patternIdx = 0; patternIdx < 8; patternIdx++)
                {

                    coefficientIdx = (patternIdx - compass + 8) % 8;
                    if (coefficient[coefficientIdx] == 0)
                        continue;

                    color = colorPattern[patternIdx];

                    switch (coefficient[coefficientIdx])
                    {
                        case 2:
                            mag[compass] += 2 * color;
                            break;
                        case 1:
                            mag[compass] += color;
                            break;
                        case -2:
                            mag[compass] -= 2 * color;
                            break;
                        case -1:
                            mag[compass] -= color;
                            break;
                    }
                }

                /* Identify strongest compass flow */
                if (compass != 0 && Math.Abs(mag[compass]) > Math.Abs(mag[compassMax]))
                    compassMax = compass;
            }

            /* Convert signed compass direction into unique flow directions (0-7) */
            flow.Plane = colorPlane;
            flow.Arrive = arrive;
            flow.Depart = (mag[compassMax] > 0) ? compassMax + 4 : compassMax;
            flow.Mag = Math.Abs(mag[compassMax]);
            flow.Loc = loc;

            return flow;
        }