Example #1
0
 private DmtxEncode(DmtxEncode src)
 {
     this._scheme = src._scheme;
     this._sizeIdxRequest = src._sizeIdxRequest;
     this._marginSize = src._marginSize;
     this._moduleSize = src._moduleSize;
     this._pixelPacking = src._pixelPacking;
     this._imageFlip = src._imageFlip;
     this._rowPadBytes = src._rowPadBytes;
     this._image = src._image;
     this._message = src._message;
     this._method = src._method;
     this._region = src._region;
 }
Example #2
0
        private List <string> DecodeImage(Bitmap image, int maxResultCount, TimeSpan timeOut, bool isMosaic)
        {
            List <string> result = new List <string>();
            int           stride;

            byte[]    rawImg  = ImageToByteArray(image, out stride);
            DmtxImage dmtxImg = new DmtxImage(rawImg, image.Width, image.Height, DmtxPackOrder.DmtxPack24bppRGB);

            dmtxImg.RowPadBytes = stride % 3;
            DmtxDecode decode    = new DmtxDecode(dmtxImg, 1);
            TimeSpan   timeLeft  = new TimeSpan(timeOut.Ticks);
            Stopwatch  stopWatch = new Stopwatch();

            stopWatch.Start();
            while (true)
            {
                if (stopWatch.Elapsed > timeOut)
                {
                    break;
                }
                DmtxRegion region = decode.RegionFindNext(timeOut);
                if (region != null)
                {
                    DmtxMessage msg     = isMosaic ? decode.MosaicRegion(region, -1) : decode.MatrixRegion(region, -1);
                    string      message = Encoding.ASCII.GetString(msg.Output);
                    message = message.Substring(0, message.IndexOf('\0'));
                    if (!result.Contains(message))
                    {
                        result.Add(message);
                        if (result.Count >= maxResultCount)
                        {
                            break;
                        }
                    }
                }
                else
                {
                    break;
                }
            }
            return(result);
        }
Example #3
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 #4
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 #5
0
        int TrailClear(DmtxRegion reg, int clearMask)
        {
            int clears;
            DmtxFollow follow;

            if (!((clearMask | 0xff) == 0xff))
            {
                throw new Exception("TrailClear mask is invalid!");
            }

            /* Clear "visited" bit from trail */
            clears = 0;
            follow = FollowSeek(reg, 0);
            while (Math.Abs(follow.Step) <= reg.StepsTotal)
            {
                if (!((int)(follow.CurrentPtr & clearMask) != 0x00))
                {
                    throw new Exception("Error performing TrailClear");
                }
                follow.CurrentPtr &= (byte)(clearMask ^ 0xff);
                follow = FollowStep(reg, follow, +1);
                clears++;
            }

            return clears;
        }
Example #6
0
        int TrailBlazeGapped(DmtxRegion reg, DmtxBresLine line, int streamDir)
        {
            bool onEdge;
            int distSq, distSqMax;
            int travel = 0;
            int outward = 0;
            int xDiff, yDiff;
            int steps;
            int stepDir = 0;
            int[] dirMap = { 0, 1, 2, 7, 8, 3, 6, 5, 4 };
            bool err;
            DmtxPixelLoc beforeStep, afterStep;
            DmtxPointFlow flow, flowNext;
            DmtxPixelLoc loc0;
            int xStep, yStep;

            loc0 = line.Loc;
            flow = GetPointFlow(reg.FlowBegin.Plane, loc0, DmtxConstants.DmtxNeighborNone);
            distSqMax = (line.XDelta * line.XDelta) + (line.YDelta * line.YDelta);
            steps = 0;
            onEdge = true;

            beforeStep = loc0;
            int beforeCacheIndex = DecodeGetCache(loc0.X, loc0.Y);
            if (beforeCacheIndex == -1)
                return 0;
            else
                _cache[beforeCacheIndex] = 0;

            do
            {
                if (onEdge == true)
                {
                    flowNext = FindStrongestNeighbor(flow, streamDir);
                    if (flowNext.Mag == DmtxConstants.DmtxUndefined)
                        break;

                    err = (new DmtxBresLine(line)).GetStep(flowNext.Loc, ref travel, ref outward);
                    if (flowNext.Mag < 50 || outward < 0 || (outward == 0 && travel < 0))
                    {
                        onEdge = false;
                    }
                    else
                    {
                        line.Step(travel, outward);
                        flow = flowNext;
                    }
                }

                if (!onEdge)
                {
                    line.Step(1, 0);
                    flow = GetPointFlow(reg.FlowBegin.Plane, line.Loc, DmtxConstants.DmtxNeighborNone);
                    if (flow.Mag > 50)
                        onEdge = true;
                }

                afterStep = line.Loc;
                int afterCacheIndex = DecodeGetCache(afterStep.X, afterStep.Y);
                if (afterCacheIndex == -1)
                    break;

                /* Determine step direction using pure magic */
                xStep = afterStep.X - beforeStep.X;
                yStep = afterStep.Y - beforeStep.Y;
                if (Math.Abs(xStep) > 1 || Math.Abs(yStep) > 1)
                {
                    throw new Exception("Invalid step directions!");
                }
                stepDir = dirMap[3 * yStep + xStep + 4];

                if (stepDir == 8)
                {
                    throw new Exception("Invalid step direction!");
                }
                if (streamDir < 0)
                {
                    this._cache[beforeCacheIndex] |= (byte)(0x40 | stepDir);
                    this._cache[afterCacheIndex] = (byte)(((stepDir + 4) % 8) << 3);
                }
                else
                {
                    this._cache[beforeCacheIndex] |= (byte)(0x40 | (stepDir << 3));
                    this._cache[afterCacheIndex] = (byte)((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;
                beforeCacheIndex = afterCacheIndex;
                steps++;

            } while (distSq < distSqMax);

            return steps;
        }
Example #7
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 #8
0
        bool FindTravelLimits(DmtxRegion reg, ref DmtxBestLine line)
        {
            int i;
            int distSq, distSqMax;
            int xDiff, yDiff;
            bool posRunning, negRunning;
            int posTravel, negTravel;
            int posWander, posWanderMin, posWanderMax, posWanderMinLock, posWanderMaxLock;
            int negWander, negWanderMin, negWanderMax, negWanderMinLock, negWanderMaxLock;
            int cosAngle, sinAngle;
            DmtxFollow followPos, followNeg;
            DmtxPixelLoc loc0, posMax, negMax;

            /* line->stepBeg is already known to sit on the best Hough line */
            followPos = followNeg = FollowSeek(reg, line.StepBeg);
            loc0 = followPos.Loc;

            cosAngle = DmtxConstants.rHvX[line.Angle];
            sinAngle = DmtxConstants.rHvY[line.Angle];

            distSqMax = 0;
            posMax = negMax = followPos.Loc;

            posTravel = negTravel = 0;
            posWander = posWanderMin = posWanderMax = posWanderMinLock = posWanderMaxLock = 0;
            negWander = negWanderMin = negWanderMax = negWanderMinLock = negWanderMaxLock = 0;

            for (i = 0; i < reg.StepsTotal / 2; i++)
            {

                posRunning = (i < 10 || Math.Abs(posWander) < Math.Abs(posTravel));
                negRunning = (i < 10 || Math.Abs(negWander) < Math.Abs(negTravel));

                if (posRunning)
                {
                    xDiff = followPos.Loc.X - loc0.X;
                    yDiff = followPos.Loc.Y - loc0.Y;
                    posTravel = (cosAngle * xDiff) + (sinAngle * yDiff);
                    posWander = (cosAngle * yDiff) - (sinAngle * xDiff);

                    if (posWander >= -3 * 256 && posWander <= 3 * 256)
                    {
                        distSq = DistanceSquared(followPos.Loc, negMax);
                        if (distSq > distSqMax)
                        {
                            posMax = followPos.Loc;
                            distSqMax = distSq;
                            line.StepPos = followPos.Step;
                            line.LocPos = followPos.Loc;
                            posWanderMinLock = posWanderMin;
                            posWanderMaxLock = posWanderMax;
                        }
                    }
                    else
                    {
                        posWanderMin = DmtxCommon.Min<int>(posWanderMin, posWander);
                        posWanderMax = DmtxCommon.Max<int>(posWanderMax, posWander);
                    }
                }
                else if (!negRunning)
                {
                    break;
                }

                if (negRunning)
                {
                    xDiff = followNeg.Loc.X - loc0.X;
                    yDiff = followNeg.Loc.Y - loc0.Y;
                    negTravel = (cosAngle * xDiff) + (sinAngle * yDiff);
                    negWander = (cosAngle * yDiff) - (sinAngle * xDiff);

                    if (negWander >= -3 * 256 && negWander < 3 * 256)
                    {
                        distSq = DistanceSquared(followNeg.Loc, posMax);
                        if (distSq > distSqMax)
                        {
                            negMax = followNeg.Loc;
                            distSqMax = distSq;
                            line.StepNeg = followNeg.Step;
                            line.LocNeg = followNeg.Loc;
                            negWanderMinLock = negWanderMin;
                            negWanderMaxLock = negWanderMax;
                        }
                    }
                    else
                    {
                        negWanderMin = DmtxCommon.Min<int>(negWanderMin, negWander);
                        negWanderMax = DmtxCommon.Max<int>(negWanderMax, negWander);
                    }
                }
                else if (!posRunning)
                {
                    break;
                }

                followPos = FollowStep(reg, followPos, +1);
                followNeg = FollowStep(reg, followNeg, -1);
            }
            line.Devn = DmtxCommon.Max<int>(posWanderMaxLock - posWanderMinLock, negWanderMaxLock - negWanderMinLock) / 256;
            line.DistSq = distSqMax;

            return true;
        }
Example #9
0
        int CountJumpTally(DmtxRegion reg, int xStart, int yStart, DmtxDirection dir)
        {
            int x, xInc = 0;
            int y, yInc = 0;
            int state = DmtxConstants.DmtxModuleOn;
            int jumpCount = 0;
            int jumpThreshold;
            int tModule, tPrev;
            bool darkOnLight;
            int color;

            if (xStart != 0 && yStart != 0)
            {
                throw new Exception("CountJumpTally failed, xStart or yStart must be zero!");
            }

            if (dir == DmtxDirection.DmtxDirRight)
            {
                xInc = 1;
            }
            else
            {
                yInc = 1;
            }

            if (xStart == -1 || xStart == reg.SymbolCols ||
                  yStart == -1 || yStart == reg.SymbolRows)
            {
                state = DmtxConstants.DmtxModuleOff;
            }

            darkOnLight = (reg.OffColor > reg.OnColor);
            jumpThreshold = Math.Abs((int)(0.4 * (reg.OnColor - reg.OffColor) + 0.5));
            color = ReadModuleColor(reg, yStart, xStart, reg.SizeIdx, reg.FlowBegin.Plane);
            tModule = (darkOnLight) ? reg.OffColor - color : color - reg.OffColor;

            for (x = xStart + xInc, y = yStart + yInc;
                  (dir == DmtxDirection.DmtxDirRight && x < reg.SymbolCols) ||
                  (dir == DmtxDirection.DmtxDirUp && y < reg.SymbolRows);
                  x += xInc, y += yInc)
            {

                tPrev = tModule;
                color = ReadModuleColor(reg, y, x, reg.SizeIdx, reg.FlowBegin.Plane);
                tModule = (darkOnLight) ? reg.OffColor - color : color - reg.OffColor;

                if (state == DmtxConstants.DmtxModuleOff)
                {
                    if (tModule > tPrev + jumpThreshold)
                    {
                        jumpCount++;
                        state = DmtxConstants.DmtxModuleOn;
                    }
                }
                else
                {
                    if (tModule < tPrev - jumpThreshold)
                    {
                        jumpCount++;
                        state = DmtxConstants.DmtxModuleOff;
                    }
                }
            }

            return jumpCount;
        }
Example #10
0
        private int ReadModuleColor(DmtxRegion reg, int symbolRow, int symbolCol, DmtxSymbolSize sizeIdx, int colorPlane)
        {
            int i;
            int symbolRows, symbolCols;
            int color, colorTmp;
            double[] sampleX = { 0.5, 0.4, 0.5, 0.6, 0.5 };
            double[] sampleY = { 0.5, 0.5, 0.4, 0.5, 0.6 };
            DmtxVector2 p = new DmtxVector2();

            symbolRows = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribSymbolRows, sizeIdx);
            symbolCols = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribSymbolCols, sizeIdx);

            colorTmp = color = 0;
            for (i = 0; i < 5; i++)
            {

                p.X = (1.0 / symbolCols) * (symbolCol + sampleX[i]);
                p.Y = (1.0 / symbolRows) * (symbolRow + sampleY[i]);

                p *= reg.Fit2raw;

                GetPixelValue((int)(p.X + 0.5), (int)(p.Y + 0.5), colorPlane, ref colorTmp);
                color += colorTmp;
            }

            return color / 5;
        }
Example #11
0
        private bool PopulateArrayFromMatrix(DmtxRegion reg, DmtxMessage msg)
        {
            /* Capture number of regions present in barcode */
            int xRegionTotal = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribHorizDataRegions, reg.SizeIdx);
            int yRegionTotal = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribVertDataRegions, reg.SizeIdx);

            /* Capture region dimensions (not including border modules) */
            int mapWidth = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribDataRegionCols, reg.SizeIdx);
            int mapHeight = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribDataRegionRows, reg.SizeIdx);

            int weightFactor = 2 * (mapHeight + mapWidth + 2);
            if (weightFactor <= 0)
            {
                throw new ArgumentException("PopulateArrayFromMatrix error: Weight Factor must be greater 0");
            }

            /* Tally module changes for each region in each direction */
            for (int yRegionCount = 0; yRegionCount < yRegionTotal; yRegionCount++)
            {

                /* Y location of mapping region origin in symbol coordinates */
                int yOrigin = yRegionCount * (mapHeight + 2) + 1;

                for (int xRegionCount = 0; xRegionCount < xRegionTotal; xRegionCount++)
                {
                    int[,] tally = new int[24, 24]; /* Large enough to map largest single region */
                    /* X location of mapping region origin in symbol coordinates */
                    int xOrigin = xRegionCount * (mapWidth + 2) + 1;

                    for (int i = 0; i < 24; i++)
                    {
                        for (int j = 0; j < 24; j++)
                        {
                            tally[i, j] = 0;
                        }
                    }
                    TallyModuleJumps(reg, tally, xOrigin, yOrigin, mapWidth, mapHeight, DmtxDirection.DmtxDirUp);
                    TallyModuleJumps(reg, tally, xOrigin, yOrigin, mapWidth, mapHeight, DmtxDirection.DmtxDirLeft);
                    TallyModuleJumps(reg, tally, xOrigin, yOrigin, mapWidth, mapHeight, DmtxDirection.DmtxDirDown);
                    TallyModuleJumps(reg, tally, xOrigin, yOrigin, mapWidth, mapHeight, DmtxDirection.DmtxDirRight);

                    /* Decide module status based on final tallies */
                    for (int mapRow = 0; mapRow < mapHeight; mapRow++)
                    {
                        for (int mapCol = 0; mapCol < mapWidth; mapCol++)
                        {

                            int rowTmp = (yRegionCount * mapHeight) + mapRow;
                            rowTmp = yRegionTotal * mapHeight - rowTmp - 1;
                            int colTmp = (xRegionCount * mapWidth) + mapCol;
                            int idx = (rowTmp * xRegionTotal * mapWidth) + colTmp;

                            if (tally[mapRow, mapCol] / (double)weightFactor >= 0.5)
                                msg.Array[idx] = (byte)DmtxConstants.DmtxModuleOnRGB;
                            else
                                msg.Array[idx] = (byte)DmtxConstants.DmtxModuleOff;

                            msg.Array[idx] |= (byte)DmtxConstants.DmtxModuleAssigned;
                        }
                    }
                }
            }

            return true;
        }
Example #12
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 #13
0
        bool MatrixRegionFindSize(DmtxRegion reg)
        {
            int row, col;
            DmtxSymbolSize sizeIdxBeg, sizeIdxEnd;
            DmtxSymbolSize sizeIdx, bestSizeIdx;
            int symbolRows, symbolCols;
            int jumpCount, errors;
            int color;
            int colorOnAvg, bestColorOnAvg;
            int colorOffAvg, bestColorOffAvg;
            int contrast, bestContrast;
            DmtxImage img;

            img = this._image;
            bestSizeIdx = DmtxSymbolSize.DmtxSymbolShapeAuto;
            bestContrast = 0;
            bestColorOnAvg = bestColorOffAvg = 0;

            if (this._sizeIdxExpected == DmtxSymbolSize.DmtxSymbolShapeAuto)
            {
                sizeIdxBeg = 0;
                sizeIdxEnd = (DmtxSymbolSize)(DmtxConstants.DmtxSymbolSquareCount + DmtxConstants.DmtxSymbolRectCount);
            }
            else if (this._sizeIdxExpected == DmtxSymbolSize.DmtxSymbolSquareAuto)
            {
                sizeIdxBeg = 0;
                sizeIdxEnd = (DmtxSymbolSize)DmtxConstants.DmtxSymbolSquareCount;
            }
            else if (this._sizeIdxExpected == DmtxSymbolSize.DmtxSymbolRectAuto)
            {
                sizeIdxBeg = (DmtxSymbolSize)DmtxConstants.DmtxSymbolSquareCount;
                sizeIdxEnd = (DmtxSymbolSize)(DmtxConstants.DmtxSymbolSquareCount + DmtxConstants.DmtxSymbolRectCount);
            }
            else
            {
                sizeIdxBeg = this._sizeIdxExpected;
                sizeIdxEnd = this._sizeIdxExpected + 1;
            }

            /* Test each barcode size to find best contrast in calibration modules */
            for (sizeIdx = sizeIdxBeg; sizeIdx < sizeIdxEnd; sizeIdx++)
            {

                symbolRows = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribSymbolRows, sizeIdx);
                symbolCols = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribSymbolCols, sizeIdx);
                colorOnAvg = colorOffAvg = 0;

                /* Sum module colors along horizontal calibration bar */
                row = symbolRows - 1;
                for (col = 0; col < symbolCols; col++)
                {
                    color = ReadModuleColor(reg, row, col, sizeIdx, reg.FlowBegin.Plane);
                    if ((col & 0x01) != 0x00)
                        colorOffAvg += color;
                    else
                        colorOnAvg += color;
                }

                /* Sum module colors along vertical calibration bar */
                col = symbolCols - 1;
                for (row = 0; row < symbolRows; row++)
                {
                    color = ReadModuleColor(reg, row, col, sizeIdx, reg.FlowBegin.Plane);
                    if ((row & 0x01) != 0x00)
                        colorOffAvg += color;
                    else
                        colorOnAvg += color;
                }

                colorOnAvg = (colorOnAvg * 2) / (symbolRows + symbolCols);
                colorOffAvg = (colorOffAvg * 2) / (symbolRows + symbolCols);

                contrast = Math.Abs(colorOnAvg - colorOffAvg);
                if (contrast < 20)
                    continue;

                if (contrast > bestContrast)
                {
                    bestContrast = contrast;
                    bestSizeIdx = sizeIdx;
                    bestColorOnAvg = colorOnAvg;
                    bestColorOffAvg = colorOffAvg;
                }
            }

            /* If no sizes produced acceptable contrast then call it quits */
            if (bestSizeIdx == DmtxSymbolSize.DmtxSymbolShapeAuto || bestContrast < 20)
                return false;

            reg.SizeIdx = bestSizeIdx;
            reg.OnColor = bestColorOnAvg;
            reg.OffColor = bestColorOffAvg;

            reg.SymbolRows = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribSymbolRows, reg.SizeIdx);
            reg.SymbolCols = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribSymbolCols, reg.SizeIdx);
            reg.MappingRows = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribMappingMatrixRows, reg.SizeIdx);
            reg.MappingCols = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribMappingMatrixCols, reg.SizeIdx);

            /* Tally jumps on horizontal calibration bar to verify sizeIdx */
            jumpCount = CountJumpTally(reg, 0, reg.SymbolRows - 1, DmtxDirection.DmtxDirRight);
            errors = Math.Abs(1 + jumpCount - reg.SymbolCols);
            if (jumpCount < 0 || errors > 2)
                return false;

            /* Tally jumps on vertical calibration bar to verify sizeIdx */
            jumpCount = CountJumpTally(reg, reg.SymbolCols - 1, 0, DmtxDirection.DmtxDirUp);
            errors = Math.Abs(1 + jumpCount - reg.SymbolRows);
            if (jumpCount < 0 || errors > 2)
                return false;

            /* Tally jumps on horizontal finder bar to verify sizeIdx */
            errors = CountJumpTally(reg, 0, 0, DmtxDirection.DmtxDirRight);
            if (jumpCount < 0 || errors > 2)
                return false;

            /* Tally jumps on vertical finder bar to verify sizeIdx */
            errors = CountJumpTally(reg, 0, 0, DmtxDirection.DmtxDirUp);
            if (errors < 0 || errors > 2)
                return false;

            /* Tally jumps on surrounding whitespace, else fail */
            errors = CountJumpTally(reg, 0, -1, DmtxDirection.DmtxDirRight);
            if (errors < 0 || errors > 2)
                return false;

            errors = CountJumpTally(reg, -1, 0, DmtxDirection.DmtxDirUp);
            if (errors < 0 || errors > 2)
                return false;

            errors = CountJumpTally(reg, 0, reg.SymbolRows, DmtxDirection.DmtxDirRight);
            if (errors < 0 || errors > 2)
                return false;

            errors = CountJumpTally(reg, reg.SymbolCols, 0, DmtxDirection.DmtxDirUp);
            if (errors < 0 || errors > 2)
                return false;

            return true;
        }
Example #14
0
        bool MatrixRegionAlignCalibEdge(DmtxRegion reg, DmtxEdge edgeLoc)
        {
            int streamDir;
            int steps;
            int avoidAngle;
            DmtxSymbolSize symbolShape;
            DmtxVector2 pTmp = new DmtxVector2();
            DmtxPixelLoc loc0 = new DmtxPixelLoc();
            DmtxPixelLoc loc1 = new DmtxPixelLoc();
            DmtxPixelLoc locOrigin = new DmtxPixelLoc();
            DmtxBresLine line;
            DmtxFollow follow;
            DmtxBestLine bestLine;

            /* Determine pixel coordinates of origin */
            pTmp.X = 0.0;
            pTmp.Y = 0.0;
            pTmp *= reg.Fit2raw;
            locOrigin.X = (int)(pTmp.X + 0.5);
            locOrigin.Y = (int)(pTmp.Y + 0.5);

            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;

            /* Determine end locations of test line */
            if (edgeLoc == DmtxEdge.DmtxEdgeTop)
            {
                streamDir = reg.Polarity * -1;
                avoidAngle = reg.LeftLine.Angle;
                follow = FollowSeekLoc(reg.LocT);
                pTmp.X = 0.8;
                pTmp.Y = (symbolShape == DmtxSymbolSize.DmtxSymbolRectAuto) ? 0.2 : 0.6;
            }
            else
            {
                streamDir = reg.Polarity;
                avoidAngle = reg.BottomLine.Angle;
                follow = FollowSeekLoc(reg.LocR);
                pTmp.X = (symbolShape == DmtxSymbolSize.DmtxSymbolSquareAuto) ? 0.7 : 0.9;
                pTmp.Y = 0.8;
            }

            pTmp *= reg.Fit2raw;
            loc1.X = (int)(pTmp.X + 0.5);
            loc1.Y = (int)(pTmp.Y + 0.5);

            loc0 = follow.Loc;
            line = new DmtxBresLine(loc0, loc1, locOrigin);
            steps = TrailBlazeGapped(reg, line, streamDir);

            bestLine = FindBestSolidLine2(loc0, steps, streamDir, avoidAngle);
            if (bestLine.Mag < 5)
            {
                ;
            }

            if (edgeLoc == DmtxEdge.DmtxEdgeTop)
            {
                reg.TopKnown = 1;
                reg.TopAngle = bestLine.Angle;
                reg.TopLoc = bestLine.LocBeg;
            }
            else
            {
                reg.RightKnown = 1;
                reg.RightAngle = bestLine.Angle;
                reg.RightLoc = bestLine.LocBeg;
            }

            return true;
        }
Example #15
0
        DmtxFollow FollowStep(DmtxRegion reg, DmtxFollow followBeg, int sign)
        {
            int patternIdx;
            int stepMod;
            int factor;
            DmtxFollow follow = new DmtxFollow();

            if (Math.Abs(sign) != 1)
            {
                throw new Exception("Invalid parameter 'sign', can only be -1 or +1");
            }

            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 = new DmtxPixelLoc() { X = followBeg.Loc.X + DmtxConstants.DmtxPatternX[patternIdx], Y = followBeg.Loc.Y + DmtxConstants.DmtxPatternY[patternIdx] };
            }

            follow.Step = followBeg.Step + sign;
            follow.Ptr = this._cache;
            follow.PtrIndex = DecodeGetCache(follow.Loc.X, follow.Loc.Y);

            return follow;
        }
Example #16
0
        internal DmtxMessage MatrixRegion(DmtxRegion reg, int fix)
        {
            DmtxMessage result = new DmtxMessage(reg.SizeIdx, DmtxFormat.Matrix);
            DmtxVector2 topLeft = new DmtxVector2();
            DmtxVector2 topRight = new DmtxVector2();
            DmtxVector2 bottomLeft = new DmtxVector2();
            DmtxVector2 bottomRight = new DmtxVector2();
            DmtxPixelLoc pxTopLeft = new DmtxPixelLoc();
            DmtxPixelLoc pxTopRight = new DmtxPixelLoc();
            DmtxPixelLoc pxBottomLeft = new DmtxPixelLoc();
            DmtxPixelLoc pxBottomRight = new DmtxPixelLoc();

            if (!PopulateArrayFromMatrix(reg, result))
            {
                throw new Exception("Populating Array from matrix failed!");
            }

            /* maybe place remaining logic into new dmtxDecodePopulatedArray()
               function so other people can pass in their own arrays */

            ModulePlacementEcc200(result.Array, result.Code,
                  reg.SizeIdx, DmtxConstants.DmtxModuleOnRed | DmtxConstants.DmtxModuleOnGreen | DmtxConstants.DmtxModuleOnBlue);

            if (DmtxCommon.DecodeCheckErrors(result.Code, 0, reg.SizeIdx, fix) != true)
            {
                return null;
            }

            topLeft.X = bottomLeft.X = topLeft.Y = topRight.Y = -0.1;
            topRight.X = bottomRight.X = bottomLeft.Y = bottomRight.Y = 1.1;

            topLeft *= reg.Fit2raw;
            topRight *= reg.Fit2raw;
            bottomLeft *= reg.Fit2raw;
            bottomLeft *= reg.Fit2raw;

            pxTopLeft.X = (int)(0.5 + topLeft.X);
            pxTopLeft.Y = (int)(0.5 + topLeft.Y);
            pxBottomLeft.X = (int)(0.5 + bottomLeft.X);
            pxBottomLeft.Y = (int)(0.5 + bottomLeft.Y);
            pxTopRight.X = (int)(0.5 + topRight.X);
            pxTopRight.Y = (int)(0.5 + topRight.Y);
            pxBottomRight.X = (int)(0.5 + bottomRight.X);
            pxBottomRight.Y = (int)(0.5 + bottomRight.Y);

            CacheFillQuad(pxTopLeft, pxTopRight, pxBottomRight, pxBottomLeft);

            result.DecodeDataStream(reg.SizeIdx, null);

            return result;
        }
Example #17
0
        internal DmtxMessage MosaicRegion(DmtxRegion reg, int fix)
        {
            DmtxMessage oMsg;

            int colorPlane = reg.FlowBegin.Plane;

            reg.FlowBegin.Plane = 0; /* kind of a hack */
            DmtxMessage rMsg = MatrixRegion(reg, fix);

            reg.FlowBegin.Plane = 1; /* kind of a hack */
            DmtxMessage gMsg = MatrixRegion(reg, fix);

            reg.FlowBegin.Plane = 2; /* kind of a hack */
            DmtxMessage bMsg = MatrixRegion(reg, fix);

            reg.FlowBegin.Plane = colorPlane;

            oMsg = new DmtxMessage(reg.SizeIdx, DmtxFormat.Mosaic);

            List<byte> totalMessage = new List<byte>();
            for (int i = 0; i < bMsg.OutputSize; i++)
            {
                if (bMsg.Output[i] == 0)
                {
                    break;
                }
                totalMessage.Add(bMsg.Output[i]);
            }
            for (int i = 0; i < gMsg.OutputSize; i++)
            {
                if (gMsg.Output[i] == 0)
                {
                    break;
                }
                totalMessage.Add(gMsg.Output[i]);
            }
            for (int i = 0; i < rMsg.OutputSize; i++)
            {
                if (rMsg.Output[i] == 0)
                {
                    break;
                }
                totalMessage.Add(rMsg.Output[i]);
            }
            totalMessage.Add(0);
            oMsg.Output = totalMessage.ToArray();
            return oMsg;
        }
Example #18
0
        DmtxRegion RegionScanPixel(int x, int y)
        {
            DmtxRegion reg = new DmtxRegion();
            DmtxPointFlow flowBegin;
            DmtxPixelLoc loc = new DmtxPixelLoc();

            loc.X = x;
            loc.Y = y;

            int cacheIndex = this.DecodeGetCache(loc.X, loc.Y);
            if (cacheIndex == -1)
                return null;

            if (this._cache[cacheIndex] != 0x00)
                return null;

            /* Test for presence of any reasonable edge at this location */
            flowBegin = MatrixRegionSeekEdge(loc);
            if (flowBegin.Mag < (int)(this._edgeThresh * 7.65 + 0.5))
                return null;

            /* Determine barcode orientation */
            if (MatrixRegionOrientation(reg, flowBegin) == false)
                return null;
            if (RegionUpdateXfrms(reg) == false)
                return null;

            /* Define top edge */
            if (MatrixRegionAlignCalibEdge(reg, DmtxEdge.DmtxEdgeTop) == false)
                return null;
            if (RegionUpdateXfrms(reg) == false)
                return null;

            /* Define right edge */
            if (MatrixRegionAlignCalibEdge(reg, DmtxEdge.DmtxEdgeRight) == false)
                return null;
            if (RegionUpdateXfrms(reg) == false)
                return null;

            //CALLBACK_MATRIX(&reg);

            /* Calculate the best fitting symbol size */
            if (MatrixRegionFindSize(reg) == false)
                return null;

            /* Found a valid matrix region */
            return new DmtxRegion(reg);
        }
Example #19
0
        DmtxBestLine FindBestSolidLine(DmtxRegion reg, int step0, int step1, int streamDir, int houghAvoid)
        {
            int[,] hough = new int[3, DmtxConstants.DmtxHoughRes];
            int houghMin, houghMax;
            char[] houghTest = new char[DmtxConstants.DmtxHoughRes];
            int i;
            int step;
            int sign = 0;
            int tripSteps = 0;
            int xDiff, yDiff;
            int dH;
            DmtxFollow follow;
            DmtxBestLine line = new DmtxBestLine();
            DmtxPixelLoc rHp;

            int angleBest = 0;
            int hOffset = 0;
            int 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 = Math.Abs(step1);
            }
            else if (step1 == 0)
            {
                sign = +1;
                tripSteps = reg.StepsTotal;
            }
            if (sign != streamDir)
            {
                throw new Exception("Sign must equal stream direction!");
            }

            follow = FollowSeek(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 < DmtxConstants.DmtxHoughRes; i++)
            {
                if (houghAvoid == DmtxConstants.DmtxUndefined)
                {
                    houghTest[i] = (char)1;
                }
                else
                {
                    houghMin = (houghAvoid + DmtxConstants.DmtxHoughRes / 6) % DmtxConstants.DmtxHoughRes;
                    houghMax = (houghAvoid - DmtxConstants.DmtxHoughRes / 6 + DmtxConstants.DmtxHoughRes) % DmtxConstants.DmtxHoughRes;
                    if (houghMin > houghMax)
                        houghTest[i] = (i > houghMin || i < houghMax) ? (char)1 : (char)0;
                    else
                        houghTest[i] = (i > houghMin && i < houghMax) ? (char)1 : (char)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 < DmtxConstants.DmtxHoughRes; i++)
                {

                    if ((int)houghTest[i] == 0)
                        continue;

                    dH = (DmtxConstants.rHvX[i] * yDiff) - (DmtxConstants.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, 2); */

                follow = FollowStep(reg, follow, sign);
            }

            line.Angle = angleBest;
            line.HOffset = hOffsetBest;
            line.Mag = hough[hOffsetBest, angleBest];

            return line;
        }
Example #20
0
        bool RegionUpdateCorners(DmtxRegion reg, DmtxVector2 p00,
     DmtxVector2 p10, DmtxVector2 p11, DmtxVector2 p01)
        {
            double xMax, yMax;
            double tx, ty, phi, shx, scx, scy, skx, sky;
            double dimOT, dimOR, dimTX, dimRX, ratio;
            DmtxVector2 vOT, vOR, vTX, vRX, vTmp;

            xMax = (double)(this.Width - 1);
            yMax = (double)(this.Height - 1);

            if (p00.X < 0.0 || p00.Y < 0.0 || p00.X > xMax || p00.Y > yMax ||
                  p01.X < 0.0 || p01.Y < 0.0 || p01.X > xMax || p01.Y > yMax ||
                  p10.X < 0.0 || p10.Y < 0.0 || p10.X > xMax || p10.Y > yMax)
                return false;

            vOT = p01 - p00;
            vOR = p10 - p00;
            vTX = p11 - p01;
            vRX = p11 - p10;
            dimOT = vOT.Mag(); /* XXX could use MagSquared() */
            dimOR = vOR.Mag();
            dimTX = vTX.Mag();
            dimRX = vRX.Mag();

            /* Verify that sides are reasonably long */
            if (dimOT <= 8.0 || dimOR <= 8.0 || dimTX <= 8.0 || dimRX <= 8.0)
                return false;

            /* Verify that the 4 corners define a reasonably fat quadrilateral */
            ratio = dimOT / dimRX;
            if (ratio <= 0.5 || ratio >= 2.0)
                return false;

            ratio = dimOR / dimTX;
            if (ratio <= 0.5 || ratio >= 2.0)
                return false;

            /* Verify this is not a bowtie shape */
            if (vOR.Cross(vRX) <= 0.0 || vOT.Cross(vTX) >= 0.0)
                return false;

            if (DmtxCommon.RightAngleTrueness(p00, p10, p11, Math.PI / 2.0) <= this._squareDevn)
                return false;
            if (DmtxCommon.RightAngleTrueness(p10, p11, p01, Math.PI / 2.0) <= this._squareDevn)
                return false;

            /* Calculate values needed for transformations */
            tx = -1 * p00.X;
            ty = -1 * p00.Y;
            DmtxMatrix3 mtxy = DmtxMatrix3.Translate(tx, ty);

            phi = Math.Atan2(vOT.X, vOT.Y);
            DmtxMatrix3 mphi = DmtxMatrix3.Rotate(phi);
            DmtxMatrix3 m = mtxy * mphi;

            vTmp = p10 * m;
            shx = -vTmp.Y / vTmp.X;
            DmtxMatrix3 mshx = DmtxMatrix3.Shear(0.0, shx);
            m *= mshx;

            scx = 1.0 / vTmp.X;
            DmtxMatrix3 mscx = DmtxMatrix3.Scale(scx, 1.0);
            m *= mscx;
            vTmp = p11 * m;

            scy = 1.0 / vTmp.Y;
            DmtxMatrix3 mscy = DmtxMatrix3.Scale(1.0, scy);
            m *= mscy;

            vTmp = p11 * m;
            skx = vTmp.X;
            DmtxMatrix3 mskx = DmtxMatrix3.LineSkewSide(1.0, skx, 1.0);
            m *= mskx;

            vTmp = p01 * m;
            sky = vTmp.Y;
            DmtxMatrix3 msky = DmtxMatrix3.LineSkewTop(sky, 1.0, 1.0);
            reg.Raw2fit = m * msky;

            /* Create inverse matrix by reverse (avoid straight matrix inversion) */
            msky = DmtxMatrix3.LineSkewTopInv(sky, 1.0, 1.0);
            mskx = DmtxMatrix3.LineSkewSideInv(1.0, skx, 1.0);
            m = msky * mskx;

            DmtxMatrix3 mscxy = DmtxMatrix3.Scale(1.0 / scx, 1.0 / scy);
            m *= mscxy;

            mshx = DmtxMatrix3.Shear(0.0, -shx);
            m *= mshx;

            mphi = DmtxMatrix3.Rotate(-phi);
            m *= mphi;

            mtxy = DmtxMatrix3.Translate(-tx, -ty);
            reg.Fit2raw = m * mtxy;

            return true;
        }
Example #21
0
        DmtxFollow FollowSeek(DmtxRegion reg, int seek)
        {
            int i;
            int sign;
            DmtxFollow follow = new DmtxFollow();

            follow.Loc = reg.FlowBegin.Loc;
            follow.Step = 0;
            follow.Ptr = this._cache;
            follow.PtrIndex = DecodeGetCache(follow.Loc.X, follow.Loc.Y);

            sign = (seek > 0) ? +1 : -1;
            for (i = 0; i != seek; i += sign)
            {
                follow = FollowStep(reg, follow, sign);
                if (Math.Abs(follow.Step) > reg.StepsTotal)
                {
                    throw new Exception("Follow step count larger total step count!");
                }
            }
            return follow;
        }
Example #22
0
        bool RegionUpdateXfrms(DmtxRegion reg)
        {
            double radians;
            DmtxRay2 rLeft = new DmtxRay2();
            DmtxRay2 rBottom = new DmtxRay2();
            DmtxRay2 rTop = new DmtxRay2();
            DmtxRay2 rRight = new DmtxRay2();
            DmtxVector2 p00 = new DmtxVector2();
            DmtxVector2 p10 = new DmtxVector2();
            DmtxVector2 p11 = new DmtxVector2();
            DmtxVector2 p01 = new DmtxVector2();

            if (!(reg.LeftKnown != 0 && reg.BottomKnown != 0))
            {
                throw new ArgumentException("Error updating Xfrms!");
            }

            /* Build ray representing left edge */
            rLeft.P.X = (double)reg.LeftLoc.X;
            rLeft.P.Y = (double)reg.LeftLoc.Y;
            radians = reg.LeftAngle * (Math.PI / DmtxConstants.DmtxHoughRes);
            rLeft.V.X = Math.Cos(radians);
            rLeft.V.Y = Math.Sin(radians);
            rLeft.TMin = 0.0;
            rLeft.TMax = rLeft.V.Norm();

            /* Build ray representing bottom edge */
            rBottom.P.X = (double)reg.BottomLoc.X;
            rBottom.P.Y = (double)reg.BottomLoc.Y;
            radians = reg.BottomAngle * (Math.PI / DmtxConstants.DmtxHoughRes);
            rBottom.V.X = Math.Cos(radians);
            rBottom.V.Y = Math.Sin(radians);
            rBottom.TMin = 0.0;
            rBottom.TMax = rBottom.V.Norm();

            /* Build ray representing top edge */
            if (reg.TopKnown != 0)
            {
                rTop.P.X = (double)reg.TopLoc.X;
                rTop.P.Y = (double)reg.TopLoc.Y;
                radians = reg.TopAngle * (Math.PI / DmtxConstants.DmtxHoughRes);
                rTop.V.X = Math.Cos(radians);
                rTop.V.Y = Math.Sin(radians);
                rTop.TMin = 0.0;
                rTop.TMax = rTop.V.Norm();
            }
            else
            {
                rTop.P.X = (double)reg.LocT.X;
                rTop.P.Y = (double)reg.LocT.Y;
                radians = reg.BottomAngle * (Math.PI / DmtxConstants.DmtxHoughRes);
                rTop.V.X = Math.Cos(radians);
                rTop.V.Y = Math.Sin(radians);
                rTop.TMin = 0.0;
                rTop.TMax = rBottom.TMax;
            }

            /* Build ray representing right edge */
            if (reg.RightKnown != 0)
            {
                rRight.P.X = (double)reg.RightLoc.X;
                rRight.P.Y = (double)reg.RightLoc.Y;
                radians = reg.RightAngle * (Math.PI / DmtxConstants.DmtxHoughRes);
                rRight.V.X = Math.Cos(radians);
                rRight.V.Y = Math.Sin(radians);
                rRight.TMin = 0.0;
                rRight.TMax = rRight.V.Norm();
            }
            else
            {
                rRight.P.X = (double)reg.LocR.X;
                rRight.P.Y = (double)reg.LocR.Y;
                radians = reg.LeftAngle * (Math.PI / DmtxConstants.DmtxHoughRes);
                rRight.V.X = Math.Cos(radians);
                rRight.V.Y = Math.Sin(radians);
                rRight.TMin = 0.0;
                rRight.TMax = rLeft.TMax;
            }

            /* Calculate 4 corners, real or imagined */
            if (!p00.Intersect(rLeft, rBottom))
                return false;

            if (!p10.Intersect(rBottom, rRight))
                return false;

            if (!p11.Intersect(rRight, rTop))
                return false;

            if (!p01.Intersect(rTop, rLeft))
                return false;

            if (!RegionUpdateCorners(reg, p00, p10, p11, p01))
                return false;

            return true;
        }
Example #23
0
        private void TallyModuleJumps(DmtxRegion reg, int[,] tally, int xOrigin, int yOrigin, int mapWidth, int mapHeight, DmtxDirection dir)
        {
            int extent, weight;
            int mapRow, mapCol;
            int lineStart, lineStop;
            int travelStart, travelStop;
            int line;
            int travel;
            int jumpThreshold;
            int color;
            int statusPrev, statusModule;
            int tPrev, tModule;

            if (!(dir == DmtxDirection.DmtxDirUp || dir == DmtxDirection.DmtxDirLeft || dir == DmtxDirection.DmtxDirDown || dir == DmtxDirection.DmtxDirRight))
            {
                throw new ArgumentException("Only orthogonal directions are allowed in tally module jumps!");
            }

            int travelStep = (dir == DmtxDirection.DmtxDirUp || dir == DmtxDirection.DmtxDirRight) ? 1 : -1;

            /* Abstract row and column progress using pointers to allow grid
               traversal in all 4 directions using same logic */
            bool horizontal = false;
            if ((dir & DmtxDirection.DmtxDirHorizontal) != 0x00)
            {
                horizontal = true;
                line = 0;
                travel = 0;
                extent = mapWidth;
                lineStart = yOrigin;
                lineStop = yOrigin + mapHeight;
                travelStart = (travelStep == 1) ? xOrigin - 1 : xOrigin + mapWidth;
                travelStop = (travelStep == 1) ? xOrigin + mapWidth : xOrigin - 1;
            }
            else
            {
                line = 0;
                travel = 0;
                extent = mapHeight;
                lineStart = xOrigin;
                lineStop = xOrigin + mapWidth;
                travelStart = (travelStep == 1) ? yOrigin - 1 : yOrigin + mapHeight;
                travelStop = (travelStep == 1) ? yOrigin + mapHeight : yOrigin - 1;
            }

            bool darkOnLight = (reg.OffColor > reg.OnColor);
            jumpThreshold = Math.Abs((int)(0.4 * (reg.OffColor - reg.OnColor) + 0.5));

            if (jumpThreshold < 0)
            {
                throw new Exception("Negative jump threshold is not allowed in tally module jumps");
            }

            for (line = lineStart; line < lineStop; line++)
            {

                /* Capture tModule for each leading border module as normal but
                   decide status based on predictable barcode border pattern */

                travel = travelStart;
                if (horizontal)
                {
                    color = ReadModuleColor(reg, line, travel, reg.SizeIdx, reg.FlowBegin.Plane);
                }
                else
                {
                    color = ReadModuleColor(reg, travel, line, reg.SizeIdx, reg.FlowBegin.Plane);
                }
                tModule = (darkOnLight) ? reg.OffColor - color : color - reg.OffColor;

                statusModule = (travelStep == 1 || (line & 0x01) == 0) ? DmtxConstants.DmtxModuleOnRGB : DmtxConstants.DmtxModuleOff;

                weight = extent;

                while ((travel += travelStep) != travelStop)
                {

                    tPrev = tModule;
                    statusPrev = statusModule;

                    /* For normal data-bearing modules capture color and decide
                       module status based on comparison to previous "known" module */

                    if (horizontal)
                    {
                        color = ReadModuleColor(reg, line, travel, reg.SizeIdx, reg.FlowBegin.Plane);
                    }
                    else
                    {
                        color = ReadModuleColor(reg, travel, line, reg.SizeIdx, reg.FlowBegin.Plane);
                    }
                    tModule = (darkOnLight) ? reg.OffColor - color : color - reg.OffColor;

                    if (statusPrev == DmtxConstants.DmtxModuleOnRGB)
                    {
                        if (tModule < tPrev - jumpThreshold)
                        {
                            statusModule = DmtxConstants.DmtxModuleOff;
                        }
                        else
                        {
                            statusModule = DmtxConstants.DmtxModuleOnRGB;
                        }
                    }
                    else if (statusPrev == DmtxConstants.DmtxModuleOff)
                    {
                        if (tModule > tPrev + jumpThreshold)
                        {
                            statusModule = DmtxConstants.DmtxModuleOnRGB;
                        }
                        else
                        {
                            statusModule = DmtxConstants.DmtxModuleOff;
                        }
                    }
                    if (horizontal)
                    {
                        mapRow = line - yOrigin;
                        mapCol = travel - xOrigin;
                    }
                    else
                    {
                        mapRow = travel - yOrigin;
                        mapCol = line - xOrigin;
                    }
                    if (!(mapRow < 24 && mapCol < 24))
                    {
                        throw new Exception("Tally module mump failed, index out of range!");
                    }

                    if (statusModule == DmtxConstants.DmtxModuleOnRGB)
                    {
                        tally[mapRow, mapCol] += (2 * weight);
                    }

                    weight--;
                }

                if (weight != 0)
                {
                    throw new Exception("Tally module jump failed, weight <> 0!");
                }
            }
        }
Example #24
0
        internal bool EncodeDataMatrix(Color? foreColor, Color? backColor, byte[] inputString)
        {
            int padCount;
            int width, height, bitsPerPixel;
            byte[] buf = new byte[4096];
            byte[] pxl;

            /* Encode input string into data codewords */
            DmtxSymbolSize sizeIdx = this._sizeIdxRequest;
            int dataWordCount = EncodeDataCodewords(buf, inputString, ref sizeIdx);
            if (dataWordCount <= 0)
            {
                return false;
            }

            /* EncodeDataCodewords() should have updated any auto sizeIdx to a real one */
            if (sizeIdx == DmtxSymbolSize.DmtxSymbolSquareAuto || sizeIdx == DmtxSymbolSize.DmtxSymbolRectAuto)
            {
                throw new Exception("Invalid symbol size for encoding!");
            }

            /* Add pad characters to match a standard symbol size (whether smallest or requested) */
            padCount = AddPadChars(buf, ref dataWordCount, DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribSymbolDataWords, sizeIdx));

            /* XXX we can remove a lot of this redundant data */
            this._region = new DmtxRegion();
            this._region.SizeIdx = sizeIdx;
            this._region.SymbolRows = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribSymbolRows, sizeIdx);
            this._region.SymbolCols = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribSymbolCols, sizeIdx);
            this._region.MappingRows = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribMappingMatrixRows, sizeIdx);
            this._region.MappingCols = DmtxCommon.GetSymbolAttribute(DmtxSymAttribute.DmtxSymAttribMappingMatrixCols, sizeIdx);

            /* Allocate memory for message and array */
            this._message = new DmtxMessage(sizeIdx, DmtxFormat.Matrix);
            this._message.PadCount = padCount;
            for (int i = 0; i < dataWordCount; i++)
            {
                this._message.Code[i] = buf[i];
            }

            /* Generate error correction codewords */
            DmtxCommon.GenReedSolEcc(this._message, this._region.SizeIdx);

            /* Module placement in region */
            DmtxDecode.ModulePlacementEcc200(this._message.Array, this._message.Code,
                  this._region.SizeIdx, DmtxConstants.DmtxModuleOnRGB);

            width = 2 * this._marginSize + (this._region.SymbolCols * this._moduleSize);
            height = 2 * this._marginSize + (this._region.SymbolRows * this._moduleSize);
            bitsPerPixel = DmtxCommon.GetBitsPerPixel(this._pixelPacking);
            if (bitsPerPixel == DmtxConstants.DmtxUndefined)
                return false;
            if (bitsPerPixel % 8 != 0)
            {
                throw new Exception("Invalid color depth for encoding!");
            }

            /* Allocate memory for the image to be generated */
            // pxl = (unsigned char *)malloc(width * height * (bitsPerPixel/8) + enc->rowPadBytes);
            pxl = new byte[width * height * (bitsPerPixel / 8) + this._rowPadBytes];

            this._image = new DmtxImage(pxl, width, height, this._pixelPacking);
            this._image.ImageFlip = this._imageFlip;
            this._image.RowPadBytes = this._rowPadBytes;

            /* Insert finder and aligment pattern modules */
            PrintPattern(foreColor, backColor);

            return true;
        }