Exemple #1
0
        public virtual PerspectiveTransform createTransform(ResultPoint topLeft, ResultPoint topRight, ResultPoint bottomLeft, ResultPoint alignmentPattern, int dimension)
        {
            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            float dimMinusThree = (float) dimension - 3.5f;
            float bottomRightX;
            float bottomRightY;
            float sourceBottomRightX;
            float sourceBottomRightY;
            if (alignmentPattern != null)
            {
                bottomRightX = alignmentPattern.X;
                bottomRightY = alignmentPattern.Y;
                sourceBottomRightX = sourceBottomRightY = dimMinusThree - 3.0f;
            }
            else
            {
                // Don't have an alignment pattern, just make up the bottom-right point
                bottomRightX = (topRight.X - topLeft.X) + bottomLeft.X;
                bottomRightY = (topRight.Y - topLeft.Y) + bottomLeft.Y;
                sourceBottomRightX = sourceBottomRightY = dimMinusThree;
            }

            PerspectiveTransform transform = PerspectiveTransform.quadrilateralToQuadrilateral(3.5f, 3.5f, dimMinusThree, 3.5f, sourceBottomRightX, sourceBottomRightY, 3.5f, dimMinusThree, topLeft.X, topLeft.Y, topRight.X, topRight.Y, bottomRightX, bottomRightY, bottomLeft.X, bottomLeft.Y);

            return transform;
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="AztecDetectorResult"/> class.
 /// </summary>
 /// <param name="bits">The bits.</param>
 /// <param name="points">The points.</param>
 /// <param name="compact">if set to <c>true</c> [compact].</param>
 /// <param name="nbDatablocks">The nb datablocks.</param>
 /// <param name="nbLayers">The nb layers.</param>
 public AztecDetectorResult(BitMatrix bits,
                            ResultPoint[] points,
                            bool compact,
                            int nbDatablocks,
                            int nbLayers)
    : base(bits, points)
 {
    Compact = compact;
    NbDatablocks = nbDatablocks;
    NbLayers = nbLayers;
 }
 /// <summary>
 /// Apply the result points' order correction due to mirroring.
 /// </summary>
 /// <param name="points">Array of points to apply mirror correction to.</param>
 internal void applyMirroredCorrection(ResultPoint[] points)
 {
    if (!mirrored || points == null || points.Length < 3)
    {
       return;
    }
    ResultPoint bottomLeft = points[0];
    points[0] = points[2];
    points[2] = bottomLeft;
    // No need to 'fix' top-left and alignment pattern.
 }
Exemple #4
0
 public Result(String text, sbyte[] rawBytes, ResultPoint[] resultPoints, BarcodeFormat format)
 {
     if (text == null && rawBytes == null)
     {
         throw new ArgumentException("Text and bytes are null");
     }
     this.text = text;
     this.rawBytes = rawBytes;
     this.resultPoints = resultPoints;
     this.format = format;
     resultMetadata = null;
 }
Exemple #5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ZXing.PDF417.Internal.BoundingBox"/> class.
        /// returns null if the corner points don't match up correctly
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="topLeft">The top left.</param>
        /// <param name="bottomLeft">The bottom left.</param>
        /// <param name="topRight">The top right.</param>
        /// <param name="bottomRight">The bottom right.</param>
        /// <returns></returns>
        public static BoundingBox Create(BitMatrix image,
                                         ResultPoint topLeft,
                                         ResultPoint bottomLeft,
                                         ResultPoint topRight,
                                         ResultPoint bottomRight)
        {
            if ((topLeft == null && topRight == null) ||
                (bottomLeft == null && bottomRight == null) ||
                (topLeft != null && bottomLeft == null) ||
                (topRight != null && bottomRight == null))
            {
                return null;
            }

            return new BoundingBox(image, topLeft, bottomLeft, topRight, bottomRight);
        }
Exemple #6
0
        /**
         * <p>Orders an array of three ResultPoints in an order [A,B,C] such that AB < AC and
         * BC < AC and the angle between BC and BA is less than 180 degrees.
         */
        public static void orderBestPatterns(ResultPoint[] patterns)
        {
            // Find distances between pattern centers
            float zeroOneDistance = distance(patterns[0], patterns[1]);
            float oneTwoDistance  = distance(patterns[1], patterns[2]);
            float zeroTwoDistance = distance(patterns[0], patterns[2]);

            ResultPoint pointA, pointB, pointC;

            // Assume one closest to other two is B; A and C will just be guesses at first
            if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance)
            {
                pointB = patterns[0];
                pointA = patterns[1];
                pointC = patterns[2];
            }
            else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance)
            {
                pointB = patterns[1];
                pointA = patterns[0];
                pointC = patterns[2];
            }
            else
            {
                pointB = patterns[2];
                pointA = patterns[0];
                pointC = patterns[1];
            }

            // Use cross product to figure out whether A and C are correct or flipped.
            // This asks whether BC x BA has a positive z component, which is the arrangement
            // we want for A, B, C. If it's negative, then we've got it flipped around and
            // should swap A and C.
            if (crossProductZ(pointA, pointB, pointC) < 0.0f)
            {
                ResultPoint temp = pointA;
                pointA = pointC;
                pointC = temp;
            }

            patterns[0] = pointA;
            patterns[1] = pointB;
            patterns[2] = pointC;
        }
Exemple #7
0
        /**
         * Counts the number of black/white transitions between two points, using something like Bresenham's algorithm.
         */
        private ResultPointsAndTransitions transitionsBetween(ResultPoint from, ResultPoint to)
        {
            // See QR Code Detector, sizeOfBlackWhiteBlackRun()
            int  fromX = (int)from.getX();
            int  fromY = (int)from.getY();
            int  toX   = (int)to.getX();
            int  toY   = (int)to.getY();
            bool steep = Math.Abs(toY - fromY) > Math.Abs(toX - fromX);

            if (steep)
            {
                int temp = fromX;
                fromX = fromY;
                fromY = temp;
                temp  = toX;
                toX   = toY;
                toY   = temp;
            }

            int  dx          = Math.Abs(toX - fromX);
            int  dy          = Math.Abs(toY - fromY);
            int  error       = -dx >> 1;
            int  ystep       = fromY < toY ? 1 : -1;
            int  xstep       = fromX < toX ? 1 : -1;
            int  transitions = 0;
            bool inBlack     = image.isBlack(steep ? fromY : fromX, steep ? fromX : fromY);

            for (int x = fromX, y = fromY; x != toX; x += xstep)
            {
                bool isBlack = image.isBlack(steep ? y : x, steep ? x : y);
                if (isBlack == !inBlack)
                {
                    transitions++;
                    inBlack = isBlack;
                }
                error += dy;
                if (error > 0)
                {
                    y     += ystep;
                    error -= dx;
                }
            }
            return(new ResultPointsAndTransitions(from, to, transitions));
        }
Exemple #8
0
        public static Individual ToIndividual(ResultPoint resultPoint)
        {
            var individual = new Individual();

            individual.Evaluations.Add(new Evaluation {
                Type = ObjectiveType.Cost, Score = resultPoint.Cost, Direction = Direction.Minimize
            });
            individual.Evaluations.Add(new Evaluation {
                Type = ObjectiveType.Macro, Score = resultPoint.Macro, Direction = Direction.Minimize
            });
            individual.Evaluations.Add(new Evaluation {
                Type = ObjectiveType.Preferences, Score = resultPoint.Preferences, Direction = Direction.Minimize
            });
            individual.Evaluations.Add(new Evaluation {
                Type = ObjectiveType.PreparationTime, Score = resultPoint.PreparationTime, Direction = Direction.Minimize
            });

            return(individual);
        }
Exemple #9
0
        /// <summary> <p>Estimates module size based on two finder patterns -- it uses
        /// {@link #sizeOfBlackWhiteBlackRunBothWays(int, int, int, int)} to figure the
        /// width of each, measuring along the axis between their centers.</p>
        /// </summary>
        private float calculateModuleSizeOneWay(ResultPoint pattern, ResultPoint otherPattern)
        {
            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            float moduleSizeEst1 = sizeOfBlackWhiteBlackRunBothWays((int)pattern.X, (int)pattern.Y, (int)otherPattern.X, (int)otherPattern.Y);
            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            float moduleSizeEst2 = sizeOfBlackWhiteBlackRunBothWays((int)otherPattern.X, (int)otherPattern.Y, (int)pattern.X, (int)pattern.Y);

            if (System.Single.IsNaN(moduleSizeEst1))
            {
                return(moduleSizeEst2 / 7.0f);
            }
            if (System.Single.IsNaN(moduleSizeEst2))
            {
                return(moduleSizeEst1 / 7.0f);
            }
            // Average them, and divide by 7 since we've counted the width of 3 black modules,
            // and 1 white and 1 black module on either side. Ergo, divide sum by 14.
            return((moduleSizeEst1 + moduleSizeEst2) / 14.0f);
        }
        /// <summary>
        /// Calculates the minimum and maximum X &amp; Y values based on the corner points.
        /// </summary>
        private void calculateMinMaxValues()
        {
            // Constructor ensures that either Left or Right is not null
            if (TopLeft == null)
            {
                TopLeft    = new ResultPoint(0, TopRight.Y);
                BottomLeft = new ResultPoint(0, BottomRight.Y);
            }
            else if (TopRight == null)
            {
                TopRight    = new ResultPoint(image.Width - 1, TopLeft.Y);
                BottomRight = new ResultPoint(image.Width - 1, TopLeft.Y);
            }

            MinX = (int)Math.Min(TopLeft.X, BottomLeft.X);
            MaxX = (int)Math.Max(TopRight.X, BottomRight.X);
            MinY = (int)Math.Min(TopLeft.Y, TopRight.Y);
            MaxY = (int)Math.Max(BottomLeft.Y, BottomRight.Y);
        }
Exemple #11
0
        // Note that we don't try rotation without the try harder flag, even if rotation was supported.
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result decode(com.google.zxing.BinaryBitmap image, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException, com.google.zxing.FormatException
        public virtual Result decode(BinaryBitmap image, IDictionary <DecodeHintType, object> hints)
        {
            try
            {
                return(doDecode(image, hints));
            }
            catch (NotFoundException nfe)
            {
                bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER);
                if (tryHarder && image.RotateSupported)
                {
                    BinaryBitmap rotatedImage = image.rotateCounterClockwise();
                    Result       result       = doDecode(rotatedImage, hints);
                    // Record that we found it rotated 90 degrees CCW / 270 degrees CW
//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
//ORIGINAL LINE: java.util.Map<com.google.zxing.ResultMetadataType,?> metadata = result.getResultMetadata();
                    IDictionary <ResultMetadataType, object> metadata = result.ResultMetadata;
                    int orientation = 270;
                    if (metadata != null && metadata.ContainsKey(ResultMetadataType.ORIENTATION))
                    {
                        // But if we found it reversed in doDecode(), add in that result here:
                        orientation = (orientation + (int)metadata[ResultMetadataType.ORIENTATION]) % 360;
                    }
                    result.putMetadata(ResultMetadataType.ORIENTATION, orientation);
                    // Update result points
                    ResultPoint[] points = result.ResultPoints;
                    if (points != null)
                    {
                        int height = rotatedImage.Height;
                        for (int i = 0; i < points.Length; i++)
                        {
                            points[i] = new ResultPoint(height - points[i].Y - 1, points[i].X);
                        }
                    }
                    return(result);
                }
                else
                {
                    throw nfe;
                }
            }
        }
Exemple #12
0
        public static double HyperVolume(List <Individual> individuals, ResultPoint resultPoint = null)
        {
            var scores = new List <double>();

            var scoreS = new StringBuilder();

            foreach (var individual in individuals)
            {
                var currentIndividualScores = individual.Evaluations.Select(e => e.Score).ToList();
                scores.AddRange(currentIndividualScores);
                foreach (var currentIndividualScore in currentIndividualScores)
                {
                    scoreS.Append(currentIndividualScore.ToString(CultureInfo.InvariantCulture) + ", ");
                }
            }

            if (resultPoint != null)
            {
                //todo finish
            }

            var engine = REngine.GetInstance();

            var data = engine.CreateNumericVector(scores.ToArray());

            engine.SetSymbol("data", data);
            engine.SetSymbol("individuals", engine.CreateNumericVector(new double[] { individuals.Count }));
            engine.SetSymbol("criterions", engine.CreateNumericVector(new double[] { individuals.First().Evaluations.Count }));

            RunScript("hv", engine);

            var hv = engine.GetSymbol("dhv").AsNumeric();

            var hvValue = hv.ToArray().First();

            if (Math.Abs(hvValue) < 0.0001)
            {
                var letsTakeABreak = true;
            }

            return(hvValue);
        }
Exemple #13
0
        /// <summary>
        /// Samples a line
        /// </summary>
        /// <param name="p1">start point (inclusive)</param>
        /// <param name="p2">end point (exclusive)</param>
        /// <param name="size">number of bits</param>
        /// <returns> the array of bits as an int (first bit is high-order bit of result)</returns>
        private int sampleLine(ResultPoint p1, ResultPoint p2, int size)
        {
            int result = 0;

            float d          = distance(p1, p2);
            float moduleSize = d / size;
            float px         = p1.X;
            float py         = p1.Y;
            float dx         = moduleSize * (p2.X - p1.X) / d;
            float dy         = moduleSize * (p2.Y - p1.Y) / d;

            for (int i = 0; i < size; i++)
            {
                if (image[MathUtils.round(px + i * dx), MathUtils.round(py + i * dy)])
                {
                    result |= 1 << (size - i - 1);
                }
            }
            return(result);
        }
Exemple #14
0
        /// <summary>
        /// Expand the square represented by the corner points by pushing out equally in all directions
        /// </summary>
        /// <param name="cornerPoints">the corners of the square, which has the bull's eye at its center</param>
        /// <param name="oldSide">the original length of the side of the square in the target bit matrix</param>
        /// <param name="newSide">the new length of the size of the square in the target bit matrix</param>
        /// <returns>the corners of the expanded square</returns>
        private static ResultPoint[] expandSquare(ResultPoint[] cornerPoints, float oldSide, float newSide)
        {
            float ratio   = newSide / (2 * oldSide);
            float dx      = cornerPoints[0].X - cornerPoints[2].X;
            float dy      = cornerPoints[0].Y - cornerPoints[2].Y;
            float centerx = (cornerPoints[0].X + cornerPoints[2].X) / 2.0f;
            float centery = (cornerPoints[0].Y + cornerPoints[2].Y) / 2.0f;

            var result0 = new ResultPoint(centerx + ratio * dx, centery + ratio * dy);
            var result2 = new ResultPoint(centerx - ratio * dx, centery - ratio * dy);

            dx      = cornerPoints[1].X - cornerPoints[3].X;
            dy      = cornerPoints[1].Y - cornerPoints[3].Y;
            centerx = (cornerPoints[1].X + cornerPoints[3].X) / 2.0f;
            centery = (cornerPoints[1].Y + cornerPoints[3].Y) / 2.0f;
            var result1 = new ResultPoint(centerx + ratio * dx, centery + ratio * dy);
            var result3 = new ResultPoint(centerx - ratio * dx, centery - ratio * dy);

            return(new ResultPoint[] { result0, result1, result2, result3 });
        }
Exemple #15
0
        private static PerspectiveTransform createTransform(ResultPoint topLeft, ResultPoint topRight, ResultPoint bottomLeft, ResultPoint alignmentPattern, int dimension)
        {
            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            float dimMinusThree = (float)dimension - 3.5f;
            float bottomRightX;
            float bottomRightY;
            float sourceBottomRightX;
            float sourceBottomRightY;

            if (alignmentPattern != null)
            {
                bottomRightX       = alignmentPattern.X;
                bottomRightY       = alignmentPattern.Y;
                sourceBottomRightX = sourceBottomRightY = dimMinusThree - 3.0f;
            }
            else
            {
                // Don't have an alignment pattern, just make up the bottom-right point
                bottomRightX       = (topRight.X - topLeft.X) + bottomLeft.X;
                bottomRightY       = (topRight.Y - topLeft.Y) + bottomLeft.Y;
                sourceBottomRightX = sourceBottomRightY = dimMinusThree;
            }

            return(PerspectiveTransform.quadrilateralToQuadrilateral(
                       3.5f,
                       3.5f,
                       dimMinusThree,
                       3.5f,
                       sourceBottomRightX,
                       sourceBottomRightY,
                       3.5f,
                       dimMinusThree,
                       topLeft.X,
                       topLeft.Y,
                       topRight.X,
                       topRight.Y,
                       bottomRightX,
                       bottomRightY,
                       bottomLeft.X,
                       bottomLeft.Y));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ZXing.PDF417.Internal.BoundingBox"/> class.
        /// Will throw an exception if the corner points don't match up correctly
        /// </summary>
        /// <param name="image">Image.</param>
        /// <param name="topLeft">Top left.</param>
        /// <param name="topRight">Top right.</param>
        /// <param name="bottomLeft">Bottom left.</param>
        /// <param name="bottomRight">Bottom right.</param>
        public BoundingBox(BitMatrix image, 
                           ResultPoint topLeft, 
                           ResultPoint bottomLeft,
                           ResultPoint topRight, 
                           ResultPoint bottomRight)
        {
            if ((topLeft == null && topRight == null) ||
                (bottomLeft == null && bottomRight == null) ||
                (topLeft != null && bottomLeft == null) ||
                (topRight != null && bottomRight == null))
            {
                throw ReaderException.Instance;
            }

            this.Image = image;
            this.TopLeft = topLeft;
            this.TopRight = topRight;
            this.BottomLeft = bottomLeft;
            this.BottomRight = bottomRight;
            CalculateMinMaxValues();
        }
        private static Point GetScanLineVector(Point[] scanLine)
        {
            ResultPoint vScan = new ResultPoint(scanLine[1].X - scanLine[0].X, scanLine[1].Y - scanLine[0].Y);
            int         dx    = Math.Sign(vScan.X);
            int         dy    = Math.Sign(vScan.Y);

            if (dx != 0 && dy != 0)
            {
                // Линия диагональная, такого быть не должно, но так как координаты float всё может быть,
                // тогда чья линия длиннее тот и прав
                if (Math.Abs(vScan.X) < Math.Abs(vScan.Y))
                {
                    dx = 0;
                }
                else
                {
                    dy = 0;
                }
            }
            return(new Point(dx, dy));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ZXing.PDF417.Internal.BoundingBox"/> class.
        /// Will throw an exception if the corner points don't match up correctly
        /// </summary>
        /// <param name="image">Image.</param>
        /// <param name="topLeft">Top left.</param>
        /// <param name="topRight">Top right.</param>
        /// <param name="bottomLeft">Bottom left.</param>
        /// <param name="bottomRight">Bottom right.</param>
        public BoundingBox(BitMatrix image,
                           ResultPoint topLeft,
                           ResultPoint bottomLeft,
                           ResultPoint topRight,
                           ResultPoint bottomRight)
        {
            if ((topLeft == null && topRight == null) ||
                (bottomLeft == null && bottomRight == null) ||
                (topLeft != null && bottomLeft == null) ||
                (topRight != null && bottomRight == null))
            {
                throw ReaderException.Instance;
            }

            this.Image       = image;
            this.TopLeft     = topLeft;
            this.TopRight    = topRight;
            this.BottomLeft  = bottomLeft;
            this.BottomRight = bottomRight;
            CalculateMinMaxValues();
        }
        /// <summary>
        /// Calculates the position of the white top right module using the output of the rectangle detector
        /// for a square matrix
        /// </summary>
        private ResultPoint correctTopRight(ResultPoint bottomLeft,
                                            ResultPoint bottomRight,
                                            ResultPoint topLeft,
                                            ResultPoint topRight,
                                            int dimension)
        {
            float corr = distance(bottomLeft, bottomRight) / (float)dimension;
            int   norm = distance(topLeft, topRight);
            float cos  = (topRight.X - topLeft.X) / norm;
            float sin  = (topRight.Y - topLeft.Y) / norm;

            ResultPoint c1 = new ResultPoint(topRight.X + corr * cos, topRight.Y + corr * sin);

            corr = distance(bottomLeft, topLeft) / (float)dimension;
            norm = distance(bottomRight, topRight);
            cos  = (topRight.X - bottomRight.X) / norm;
            sin  = (topRight.Y - bottomRight.Y) / norm;

            ResultPoint c2 = new ResultPoint(topRight.X + corr * cos, topRight.Y + corr * sin);

            if (!isValid(c1))
            {
                if (isValid(c2))
                {
                    return(c2);
                }
                return(null);
            }
            if (!isValid(c2))
            {
                return(c1);
            }

            int l1 = Math.Abs(transitionsBetween(topLeft, c1).Transitions -
                              transitionsBetween(bottomRight, c1).Transitions);
            int l2 = Math.Abs(transitionsBetween(topLeft, c2).Transitions -
                              transitionsBetween(bottomRight, c2).Transitions);

            return(l1 <= l2 ? c1 : c2);
        }
Exemple #20
0
        /// <summary>
        /// Locates and decodes a barcode in some format within an image. This method also accepts
        /// hints, each possibly associated to some data, which may help the implementation decode.
        /// Note that we don't try rotation without the try harder flag, even if rotation was supported.
        /// </summary>
        /// <param name="image">image of barcode to decode</param>
        /// <param name="hints">passed as a <see cref="IDictionary{TKey, TValue}"/> from <see cref="DecodeHintType"/>
        /// to arbitrary data. The
        /// meaning of the data depends upon the hint type. The implementation may or may not do
        /// anything with these hints.</param>
        /// <returns>
        /// String which the barcode encodes
        /// </returns>
        virtual public Result decode(BinaryBitmap image, IDictionary <DecodeHintType, object> hints)
        {
            var result = doDecode(image, hints);

            if (result == null)
            {
                bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER);
                bool tryHarderWithoutRotation = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER_WITHOUT_ROTATION);
                if (tryHarder && !tryHarderWithoutRotation && image.RotateSupported)
                {
                    BinaryBitmap rotatedImage = image.rotateCounterClockwise();
                    result = doDecode(rotatedImage, hints);
                    if (result == null)
                    {
                        return(null);
                    }
                    // Record that we found it rotated 90 degrees CCW / 270 degrees CW
                    IDictionary <ResultMetadataType, object> metadata = result.ResultMetadata;
                    int orientation = 270;
                    if (metadata != null && metadata.ContainsKey(ResultMetadataType.ORIENTATION))
                    {
                        // But if we found it reversed in doDecode(), add in that result here:
                        orientation = (orientation +
                                       (int)metadata[ResultMetadataType.ORIENTATION]) % 360;
                    }
                    result.putMetadata(ResultMetadataType.ORIENTATION, orientation);
                    // Update result points
                    ResultPoint[] points = result.ResultPoints;
                    if (points != null)
                    {
                        int height = rotatedImage.Height;
                        for (int i = 0; i < points.Length; i++)
                        {
                            points[i] = new ResultPoint(height - points[i].Y - 1, points[i].X);
                        }
                    }
                }
            }
            return(result);
        }
Exemple #21
0
        /// <summary>
        /// Detect a second solid side next to first solid side.
        /// </summary>
        /// <param name="points"></param>
        /// <returns></returns>
        private ResultPoint[] detectSolid2(ResultPoint[] points)
        {
            // A..D
            // :  :
            // B--C
            ResultPoint pointA = points[0];
            ResultPoint pointB = points[1];
            ResultPoint pointC = points[2];
            ResultPoint pointD = points[3];

            // Transition detection on the edge is not stable.
            // To safely detect, shift the points to the module center.
            int         tr      = transitionsBetween(pointA, pointD);
            ResultPoint pointBs = shiftPoint(pointB, pointC, (tr + 1) * 4);
            ResultPoint pointCs = shiftPoint(pointC, pointB, (tr + 1) * 4);
            int         trBA    = transitionsBetween(pointBs, pointA);
            int         trCD    = transitionsBetween(pointCs, pointD);

            // 0..3
            // |  :
            // 1--2
            if (trBA < trCD)
            {
                // solid sides: A-B-C
                points[0] = pointA;
                points[1] = pointB;
                points[2] = pointC;
                points[3] = pointD;
            }
            else
            {
                // solid sides: B-C-D
                points[0] = pointB;
                points[1] = pointC;
                points[2] = pointD;
                points[3] = pointA;
            }

            return(points);
        }
Exemple #22
0
        /// <summary>
        /// recenters the points of a constant distance towards the center
        /// </summary>
        /// <param name="y">bottom most point</param>
        /// <param name="z">left most point</param>
        /// <param name="x">right most point</param>
        /// <param name="t">top most point</param>
        /// <returns><see cref="ResultPoint"/>[] describing the corners of the rectangular
        /// region. The first and last points are opposed on the diagonal, as
        /// are the second and third. The first point will be the topmost
        /// point and the last, the bottommost. The second point will be
        /// leftmost and the third, the rightmost</returns>
        private ResultPoint[] centerEdges(ResultPoint y, ResultPoint z,
                                          ResultPoint x, ResultPoint t)
        {
            //
            //       t            t
            //  z                      x
            //        x    OR    z
            //   y                    y
            //

            float yi = y.X;
            float yj = y.Y;
            float zi = z.X;
            float zj = z.Y;
            float xi = x.X;
            float xj = x.Y;
            float ti = t.X;
            float tj = t.Y;

            if (yi < width / 2.0f)
            {
                return(new[]
                {
                    new ResultPoint(ti - CORR, tj + CORR),
                    new ResultPoint(zi + CORR, zj + CORR),
                    new ResultPoint(xi - CORR, xj - CORR),
                    new ResultPoint(yi + CORR, yj - CORR)
                });
            }
            else
            {
                return(new[]
                {
                    new ResultPoint(ti + CORR, tj + CORR),
                    new ResultPoint(zi + CORR, zj - CORR),
                    new ResultPoint(xi - CORR, xj + CORR),
                    new ResultPoint(yi - CORR, yj - CORR)
                });
            }
        }
Exemple #23
0
        /// <summary>
        /// <p>Computes the dimension (number of modules on a size) of the QR Code based on the position
        /// of the finder patterns and estimated module size.</p>
        /// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static int computeDimension(com.google.zxing.ResultPoint topLeft, com.google.zxing.ResultPoint topRight, com.google.zxing.ResultPoint bottomLeft, float moduleSize) throws com.google.zxing.NotFoundException
        private static int computeDimension(ResultPoint topLeft, ResultPoint topRight, ResultPoint bottomLeft, float moduleSize)
        {
            int tltrCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, topRight) / moduleSize);
            int tlblCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, bottomLeft) / moduleSize);
            int dimension            = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7;

            switch (dimension & 0x03)     // mod 4
            {
            case 0:
                dimension++;
                break;

            // 1? do nothing
            case 2:
                dimension--;
                break;

            case 3:
                throw NotFoundException.NotFoundInstance;
            }
            return(dimension);
        }
Exemple #24
0
        public static double HyperVolume(List <ResultPoint> resultPoints, ResultPoint referencePoint = null)
        {
            var scores = new List <double>();
            var engine = REngine.GetInstance();

            engine.ClearGlobalEnvironment();

            foreach (var point in resultPoints)
            {
                scores.Add(point.Macro);
                scores.Add(point.PreparationTime);
                scores.Add(point.Cost);
                scores.Add(point.Preferences);
            }

            if (referencePoint != null)
            {
                engine.SetSymbol("useReferecnePoint", engine.CreateLogical(true));
                engine.SetSymbol("referencePoint", engine.CreateNumericVector(new []
                {
                    referencePoint.Macro, referencePoint.PreparationTime, referencePoint.Cost, referencePoint.Preferences
                }));
            }
            else
            {
                engine.SetSymbol("useReferecnePoint", engine.CreateLogical(false));
            }

            engine.SetSymbol("data", engine.CreateNumericVector(scores.ToArray()));
            engine.SetSymbol("individuals", engine.CreateNumericVector(new double[] { resultPoints.Count }));
            engine.SetSymbol("criterions", engine.CreateNumericVector(new double[] { 4 }));

            RunScript("hv", engine);

            var hv = engine.GetSymbol("dhv").AsNumeric().ToArray().First();

            return(hv);
        }
        private static ResultPoint[] GetBarCodeRect(Point[] scanLine, ResultPoint[] whiterect, float dx)
        {
            ResultPoint pt0 = new ResultPoint(scanLine[0].X, scanLine[0].Y); // Начало линии сканирования (заканчивается за 3 штрихполоски до начала штрихкода)
            ResultPoint pt1 = new ResultPoint(scanLine[1].X, scanLine[1].Y); // Конец линии сканирования (заканчивается за 3 штрихполоски до конца штрихкода)

            // whiterect п/у ограничивающий одну или несколько полосок штрих кода,
            // сделаем его направленным, повернем вдоль скан линии, чтобы можно было ширину расширить
            whiterect = RotateRect(whiterect, scanLine);

            // Проекция точки x,y на найденную полоску штрихкода.
            ResultPoint proj = Projection(pt1, whiterect[1], whiterect[0]);
            float       vLen = ResultPoint.distance(pt1, proj);
            ResultPoint v    = new ResultPoint(pt1.X - proj.X, pt1.Y - proj.Y);

            // Вектор b перпендикулярный вектору a против часовой стрелки равен  b = (-ay, ax).
            // Найдем правую нормаль к вертикальной полоске
            float       height = ResultPoint.distance(whiterect[1], whiterect[0]);
            ResultPoint vOrto  = new ResultPoint(-(whiterect[1].Y - whiterect[0].Y) / height, (whiterect[1].X - whiterect[0].X) / height);

            var lastBarCodeLine = new ResultPoint[2] {
                new ResultPoint(whiterect[0].X + v.X - vOrto.X * dx, whiterect[0].Y + v.Y - vOrto.Y * dx),
                new ResultPoint(whiterect[1].X + v.X - vOrto.X * dx, whiterect[1].Y + v.Y - vOrto.Y * dx)
            };

            ResultPoint proj0            = Projection(pt0, whiterect[1], whiterect[0]);
            ResultPoint v0               = new ResultPoint(pt0.X - proj0.X, pt0.Y - proj0.Y);
            var         firstBarCodeLine = new ResultPoint[2] {
                new ResultPoint(whiterect[0].X + v0.X + vOrto.X * dx, whiterect[0].Y + v0.Y + vOrto.Y * dx),
                new ResultPoint(whiterect[1].X + v0.X + vOrto.X * dx, whiterect[1].Y + v0.Y + vOrto.Y * dx)
            };

            return(new ResultPoint[] {
                firstBarCodeLine[0],
                firstBarCodeLine[1],
                lastBarCodeLine[0],
                lastBarCodeLine[1]
            });
        }
Exemple #26
0
        /**
         * <p>Estimates module size based on two finder patterns -- it uses
         * {@link #sizeOfBlackWhiteBlackRunBothWays(int, int, int, int)} to figure the
         * width of each, measuring along the axis between their centers.</p>
         */
        private float calculateModuleSizeOneWay(ResultPoint pattern, ResultPoint otherPattern)
        {
            float moduleSizeEst1 = sizeOfBlackWhiteBlackRunBothWays((int)pattern.getX(),
                                                                    (int)pattern.getY(),
                                                                    (int)otherPattern.getX(),
                                                                    (int)otherPattern.getY());
            float moduleSizeEst2 = sizeOfBlackWhiteBlackRunBothWays((int)otherPattern.getX(),
                                                                    (int)otherPattern.getY(),
                                                                    (int)pattern.getX(),
                                                                    (int)pattern.getY());

            if (Single.IsNaN(moduleSizeEst1))
            {
                return(moduleSizeEst2);
            }
            if (Single.IsNaN(moduleSizeEst2))
            {
                return(moduleSizeEst1);
            }
            // Average them, and divide by 7 since we've counted the width of 3 black modules,
            // and 1 white and 1 black module on either side. Ergo, divide sum by 14.
            return((moduleSizeEst1 + moduleSizeEst2) / 14.0f);
        }
Exemple #27
0
        /// <summary> <p>Computes the dimension (number of modules on a size) of the QR Code based on the position
        /// of the finder patterns and estimated module size.</p>
        /// </summary>
        protected internal static int computeDimension(ResultPoint topLeft, ResultPoint topRight, ResultPoint bottomLeft, float moduleSize)
        {
            int tltrCentersDimension = round(ResultPoint.distance(topLeft, topRight) / moduleSize);
            int tlblCentersDimension = round(ResultPoint.distance(topLeft, bottomLeft) / moduleSize);
            int dimension            = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7;

            switch (dimension & 0x03)
            {
            // mod 4
            case 0:
                dimension++;
                break;
            // 1? do nothing

            case 2:
                dimension--;
                break;

            case 3:
                throw ReaderException.Instance;
            }
            return(dimension);
        }
Exemple #28
0
        /// <summary> <p>Computes the dimension (number of modules on a size) of the QR Code based on the position
        /// of the finder patterns and estimated module size.</p>
        /// </summary>
        private static bool computeDimension(ResultPoint topLeft, ResultPoint topRight, ResultPoint bottomLeft, float moduleSize, out int dimension)
        {
            int tltrCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, topRight) / moduleSize);
            int tlblCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, bottomLeft) / moduleSize);

            dimension = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7;
            switch (dimension & 0x03)
            {
            // mod 4
            case 0:
                dimension++;
                break;

            // 1? do nothing
            case 2:
                dimension--;
                break;

            case 3:
                return(true);
            }
            return(true);
        }
            /**
           * <p>Orders an array of three ResultPoints in an order [A,B,C] such that AB < AC and
           * BC < AC and the angle between BC and BA is less than 180 degrees.
           */
          public static void orderBestPatterns(ResultPoint[] patterns) {

            // Find distances between pattern centers
            float zeroOneDistance = distance(patterns[0], patterns[1]);
            float oneTwoDistance = distance(patterns[1], patterns[2]);
            float zeroTwoDistance = distance(patterns[0], patterns[2]);

            ResultPoint pointA, pointB, pointC;
            // Assume one closest to other two is B; A and C will just be guesses at first
            if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance) {
              pointB = patterns[0];
              pointA = patterns[1];
              pointC = patterns[2];
            } else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance) {
              pointB = patterns[1];
              pointA = patterns[0];
              pointC = patterns[2];
            } else {
              pointB = patterns[2];
              pointA = patterns[0];
              pointC = patterns[1];
            }

            // Use cross product to figure out whether A and C are correct or flipped.
            // This asks whether BC x BA has a positive z component, which is the arrangement
            // we want for A, B, C. If it's negative, then we've got it flipped around and
            // should swap A and C.
            if (crossProductZ(pointA, pointB, pointC) < 0.0f) {
              ResultPoint temp = pointA;
              pointA = pointC;
              pointC = temp;
            }

            patterns[0] = pointA;
            patterns[1] = pointB;
            patterns[2] = pointC;
          }
Exemple #30
0
 // Note that we don't try rotation without the try harder flag, even if rotation was supported.
 public virtual Result Decode(BinaryBitmap image, System.Collections.Hashtable hints)
 {
     try
     {
         return(doDecode(image, hints));
     }
     catch (ReaderException re)
     {
         bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER);
         if (tryHarder && image.RotateSupported)
         {
             BinaryBitmap rotatedImage = image.rotateCounterClockwise();
             Result       result       = doDecode(rotatedImage, hints);
             // Record that we found it rotated 90 degrees CCW / 270 degrees CW
             System.Collections.Hashtable metadata = result.ResultMetadata;
             int orientation = 270;
             if (metadata != null && metadata.ContainsKey(ResultMetadataType.ORIENTATION))
             {
                 // But if we found it reversed in doDecode(), add in that result here:
                 orientation = (orientation + ((System.Int32)metadata[ResultMetadataType.ORIENTATION])) % 360;
             }
             result.putMetadata(ResultMetadataType.ORIENTATION, (System.Object)orientation);
             // Update result points
             ResultPoint[] points = result.ResultPoints;
             int           height = rotatedImage.Height;
             for (int i = 0; i < points.Length; i++)
             {
                 points[i] = new ResultPoint(height - points[i].Y - 1, points[i].X);
             }
             return(result);
         }
         else
         {
             throw re;
         }
     }
 }
 // Note that we don't try rotation without the try harder flag, even if rotation was supported.
 public virtual Result decode(BinaryBitmap image, System.Collections.Generic.Dictionary <Object,Object> hints)
 {
     try
     {
         return doDecode(image, hints);
     }
     catch (ReaderException re)
     {
         bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER);
         if (tryHarder && image.RotateSupported)
         {
             BinaryBitmap rotatedImage = image.rotateCounterClockwise();
             Result result = doDecode(rotatedImage, hints);
             // Record that we found it rotated 90 degrees CCW / 270 degrees CW
             System.Collections.Generic.Dictionary <Object,Object> metadata = result.ResultMetadata;
             int orientation = 270;
             if (metadata != null && metadata.ContainsKey(ResultMetadataType.ORIENTATION))
             {
                 // But if we found it reversed in doDecode(), add in that result here:
                 orientation = (orientation + ((System.Int32) metadata[ResultMetadataType.ORIENTATION])) % 360;
             }
             result.putMetadata(ResultMetadataType.ORIENTATION, (System.Object) orientation);
             // Update result points
             ResultPoint[] points = result.ResultPoints;
             int height = rotatedImage.Height;
             for (int i = 0; i < points.Length; i++)
             {
                 points[i] = new ResultPoint(height - points[i].Y - 1, points[i].X);
             }
             return result;
         }
         else
         {
             throw re;
         }
     }
 }
Exemple #32
0
        private static BitMatrix sampleGrid(MonochromeBitmapSource image,
                                            ResultPoint topLeft,
                                            ResultPoint bottomLeft,
                                            ResultPoint bottomRight,
                                            int dimension)
        {
            // We make up the top right point for now, based on the others.
            // TODO: we actually found a fourth corner above and figured out which of two modules
            // it was the corner of. We could use that here and adjust for perspective distortion.
            float topRightX = (bottomRight.getX() - bottomLeft.getX()) + topLeft.getX();
            float topRightY = (bottomRight.getY() - bottomLeft.getY()) + topLeft.getY();

            // Note that unlike in the QR Code sampler, we didn't find the center of modules, but the
            // very corners. So there is no 0.5f here; 0.0f is right.
            GridSampler sampler = GridSampler.Instance;

            return(sampler.sampleGrid(
                       image,
                       dimension,
                       0.0f,
                       0.0f,
                       dimension,
                       0.0f,
                       dimension,
                       dimension,
                       0.0f,
                       dimension,
                       topLeft.getX(),
                       topLeft.getY(),
                       topRightX,
                       topRightY,
                       bottomRight.getX(),
                       bottomRight.getY(),
                       bottomLeft.getX(),
                       bottomLeft.getY()));
        }
Exemple #33
0
        /// <summary>
        /// Creates a BitMatrix by sampling the provided image.
        /// topLeft, topRight, bottomRight, and bottomLeft are the centers of the squares on the
        /// diagonal just outside the bull's eye.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="topLeft">The top left.</param>
        /// <param name="bottomLeft">The bottom left.</param>
        /// <param name="bottomRight">The bottom right.</param>
        /// <param name="topRight">The top right.</param>
        /// <returns></returns>
        private BitMatrix sampleGrid(BitMatrix image,
                                     ResultPoint topLeft,
                                     ResultPoint topRight,
                                     ResultPoint bottomRight,
                                     ResultPoint bottomLeft)
        {
            GridSampler sampler   = GridSampler.Instance;
            int         dimension = getDimension();

            float low  = dimension / 2.0f - nbCenterLayers;
            float high = dimension / 2.0f + nbCenterLayers;

            return(sampler.sampleGrid(image,
                                      dimension,
                                      dimension,
                                      low, low,   // topleft
                                      high, low,  // topright
                                      high, high, // bottomright
                                      low, high,  // bottomleft
                                      topLeft.X, topLeft.Y,
                                      topRight.X, topRight.Y,
                                      bottomRight.X, bottomRight.Y,
                                      bottomLeft.X, bottomLeft.Y));
        }
Exemple #34
0
 /// <summary> Increments the Integer associated with a key by one.</summary>
 private static void  increment(System.Collections.Hashtable table, ResultPoint key)
 {
     //System.Int32 value_Renamed = (System.Int32) table[key];
     ////UPGRADE_TODO: The 'System.Int32' structure does not have an equivalent to NULL. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1291'"
     //table[key] = value_Renamed == null?INTEGERS[1]:INTEGERS[value_Renamed + 1];
     // Redivivus.in Java to c# Porting update
     // 30/01/2010
     // Added
     // START
     System.Int32 value_Renamed = 0;
     try
     {
         if (table.Count > 0)
         {
             value_Renamed = (System.Int32)table[key];
         }
     }
     catch
     {
         value_Renamed = 0;
     }
     table[key] = value_Renamed == 0 ? INTEGERS[1] : INTEGERS[value_Renamed + 1];
     //END
 }
Exemple #35
0
        protected internal virtual DetectorResult processFinderPatternInfo(FinderPatternInfo info)
        {
            FinderPattern topLeft    = info.TopLeft;
            FinderPattern topRight   = info.TopRight;
            FinderPattern bottomLeft = info.BottomLeft;

            float moduleSize = calculateModuleSize(topLeft, topRight, bottomLeft);

            if (moduleSize < 1.0f)
            {
                throw ReaderException.Instance;
            }
            int     dimension               = computeDimension(topLeft, topRight, bottomLeft, moduleSize);
            Version provisionalVersion      = Version.getProvisionalVersionForDimension(dimension);
            int     modulesBetweenFPCenters = provisionalVersion.DimensionForVersion - 7;

            PerspectiveTransform transform = createTransform(topLeft, topRight, bottomLeft, dimension);

            BitMatrix bits = sampleGrid(image, transform, dimension);

            ResultPoint[] points;
            points = new ResultPoint[] { bottomLeft, topLeft, topRight };
            return(new DetectorResult(bits, points));
        }
Exemple #36
0
      /// <summary>
      /// Samples an Aztec matrix from an image
      /// </summary>
      /// <param name="image">The image.</param>
      /// <param name="topLeft">The top left.</param>
      /// <param name="bottomLeft">The bottom left.</param>
      /// <param name="bottomRight">The bottom right.</param>
      /// <param name="topRight">The top right.</param>
      /// <returns></returns>
      private BitMatrix sampleGrid(BitMatrix image,
                                   ResultPoint topLeft,
                                   ResultPoint bottomLeft,
                                   ResultPoint bottomRight,
                                   ResultPoint topRight)
      {
         int dimension;
         if (compact)
         {
            dimension = 4 * nbLayers + 11;
         }
         else
         {
            if (nbLayers <= 4)
            {
               dimension = 4 * nbLayers + 15;
            }
            else
            {
               dimension = 4 * nbLayers + 2 * ((nbLayers - 4) / 8 + 1) + 15;
            }
         }

         GridSampler sampler = GridSampler.Instance;

         return sampler.sampleGrid(image,
           dimension,
           dimension,
           0.5f,
           0.5f,
           dimension - 0.5f,
           0.5f,
           dimension - 0.5f,
           dimension - 0.5f,
           0.5f,
           dimension - 0.5f,
           topLeft.X,
           topLeft.Y,
           topRight.X,
           topRight.Y,
           bottomRight.X,
           bottomRight.Y,
           bottomLeft.X,
           bottomLeft.Y);
      }
      /// <summary>
      /// recenters the points of a constant distance towards the center
      /// </summary>
      /// <param name="y">bottom most point</param>
      /// <param name="z">left most point</param>
      /// <param name="x">right most point</param>
      /// <param name="t">top most point</param>
      /// <returns><see cref="ResultPoint"/>[] describing the corners of the rectangular
      /// region. The first and last points are opposed on the diagonal, as
      /// are the second and third. The first point will be the topmost
      /// point and the last, the bottommost. The second point will be
      /// leftmost and the third, the rightmost</returns>
      private ResultPoint[] centerEdges(ResultPoint y, ResultPoint z,
                                        ResultPoint x, ResultPoint t)
      {
         //
         //       t            t
         //  z                      x
         //        x    OR    z
         //   y                    y
         //

         float yi = y.X;
         float yj = y.Y;
         float zi = z.X;
         float zj = z.Y;
         float xi = x.X;
         float xj = x.Y;
         float ti = t.X;
         float tj = t.Y;

         if (yi < width / 2.0f)
         {
            return new[]
                      {
                         new ResultPoint(ti - CORR, tj + CORR),
                         new ResultPoint(zi + CORR, zj + CORR),
                         new ResultPoint(xi - CORR, xj - CORR),
                         new ResultPoint(yi + CORR, yj - CORR)
                      };
         }
         else
         {
            return new[]
                      {
                         new ResultPoint(ti + CORR, tj + CORR),
                         new ResultPoint(zi + CORR, zj - CORR),
                         new ResultPoint(xi - CORR, xj + CORR),
                         new ResultPoint(yi - CORR, yj - CORR)
                      };
         }
      }
Exemple #38
0
 /// <summary>
 /// If we adjust the width, set a new right corner coordinate and recalculate
 /// </summary>
 /// <param name="bottomRight">Bottom right.</param>
 internal void SetBottomRight(ResultPoint bottomRight)
 {
     this.BottomRight = bottomRight;
     calculateMinMaxValues();
 }
Exemple #39
0
        /// <summary>
        /// Calculates the minimum and maximum X &amp; Y values based on the corner points.
        /// </summary>
        private void calculateMinMaxValues()
        {
            // Constructor ensures that either Left or Right is not null
            if (TopLeft == null)
            {
                TopLeft = new ResultPoint(0, TopRight.Y);
                BottomLeft = new ResultPoint(0, BottomRight.Y);
            }
            else if (TopRight == null)
            {
                TopRight = new ResultPoint(image.Width - 1, TopLeft.Y);
                BottomRight = new ResultPoint(image.Width - 1, TopLeft.Y);
            }

            MinX = (int)Math.Min(TopLeft.X, BottomLeft.X);
            MaxX = (int)Math.Max(TopRight.X, BottomRight.X);
            MinY = (int)Math.Min(TopLeft.Y, TopRight.Y);
            MaxY = (int)Math.Max(BottomLeft.Y, BottomRight.Y);

        }
Exemple #40
0
        /// <summary>
        /// Adds the missing rows.
        /// </summary>
        /// <returns>The missing rows.</returns>
        /// <param name="missingStartRows">Missing start rows.</param>
        /// <param name="missingEndRows">Missing end rows.</param>
        /// <param name="isLeft">If set to <c>true</c> is left.</param>
        public BoundingBox addMissingRows(int missingStartRows, int missingEndRows, bool isLeft)
        {
            ResultPoint newTopLeft = TopLeft;
            ResultPoint newBottomLeft = BottomLeft;
            ResultPoint newTopRight = TopRight;
            ResultPoint newBottomRight = BottomRight;

            if (missingStartRows > 0)
            {
                ResultPoint top = isLeft ? TopLeft : TopRight;
                int newMinY = (int)top.Y - missingStartRows;
                if (newMinY < 0)
                {
                    newMinY = 0;
                }
                // TODO use existing points to better interpolate the new x positions
                ResultPoint newTop = new ResultPoint(top.X, newMinY);
                if (isLeft)
                {
                    newTopLeft = newTop;
                }
                else
                {
                    newTopRight = newTop;
                }
            }

            if (missingEndRows > 0)
            {
                ResultPoint bottom = isLeft ? BottomLeft : BottomRight;
                int newMaxY = (int)bottom.Y + missingEndRows;
                if (newMaxY >= image.Height)
                {
                    newMaxY = image.Height - 1;
                }
                // TODO use existing points to better interpolate the new x positions
                ResultPoint newBottom = new ResultPoint(bottom.X, newMaxY);
                if (isLeft)
                {
                    newBottomLeft = newBottom;
                }
                else
                {
                    newBottomRight = newBottom;
                }
            }

            calculateMinMaxValues();
            return new BoundingBox(image, newTopLeft, newBottomLeft, newTopRight, newBottomRight);
        }
Exemple #41
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ZXing.PDF417.Internal.BoundingBox"/> class.
 /// Will throw an exception if the corner points don't match up correctly
 /// </summary>
 /// <param name="image">Image.</param>
 /// <param name="topLeft">Top left.</param>
 /// <param name="topRight">Top right.</param>
 /// <param name="bottomLeft">Bottom left.</param>
 /// <param name="bottomRight">Bottom right.</param>
 private BoundingBox(BitMatrix image,
                     ResultPoint topLeft,
                     ResultPoint bottomLeft,
                     ResultPoint topRight,
                     ResultPoint bottomRight)
 {
     this.image = image;
     this.TopLeft = topLeft;
     this.TopRight = topRight;
     this.BottomLeft = bottomLeft;
     this.BottomRight = bottomRight;
     calculateMinMaxValues();
 }
Exemple #42
0
 /// <summary> <p>Computes the dimension (number of modules on a size) of the QR Code based on the position
 /// of the finder patterns and estimated module size.</p>
 /// </summary>
 private static bool computeDimension(ResultPoint topLeft, ResultPoint topRight, ResultPoint bottomLeft, float moduleSize, out int dimension)
 {
    int tltrCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, topRight) / moduleSize);
    int tlblCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, bottomLeft) / moduleSize);
    dimension = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7;
    switch (dimension & 0x03)
    {
       // mod 4
       case 0:
          dimension++;
          break;
       // 1? do nothing
       case 2:
          dimension--;
          break;
       case 3:
          return true;
    }
    return true;
 }
 /// <summary>
 /// Gets the minimum width of the codeword.
 /// </summary>
 /// <returns>The minimum codeword width.</returns>
 /// <param name="p">P.</param>
 private static int GetMinCodewordWidth(ResultPoint[] p)
 {
     return Math.Min(
         Math.Min(GetMinWidth(p[0], p[4]), GetMinWidth(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD /
         PDF417Common.MODULES_IN_STOP_PATTERN),
         Math.Min(GetMinWidth(p[1], p[5]), GetMinWidth(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD /
         PDF417Common.MODULES_IN_STOP_PATTERN));
 }
 /// <summary>
 /// Gets the row indicator column.
 /// </summary>
 /// <returns>The row indicator column.</returns>
 /// <param name="image">Image.</param>
 /// <param name="boundingBox">Bounding box.</param>
 /// <param name="startPoint">Start point.</param>
 /// <param name="leftToRight">If set to <c>true</c> left to right.</param>
 /// <param name="minCodewordWidth">Minimum codeword width.</param>
 /// <param name="maxCodewordWidth">Max codeword width.</param>
 private static DetectionResultRowIndicatorColumn getRowIndicatorColumn(BitMatrix image,
                                                                        BoundingBox boundingBox,
                                                                        ResultPoint startPoint,
                                                                        bool leftToRight,
                                                                        int minCodewordWidth,
                                                                        int maxCodewordWidth)
 {
    DetectionResultRowIndicatorColumn rowIndicatorColumn = new DetectionResultRowIndicatorColumn(boundingBox, leftToRight);
    for (int i = 0; i < 2; i++)
    {
       int increment = i == 0 ? 1 : -1;
       int startColumn = (int) startPoint.X;
       for (int imageRow = (int) startPoint.Y; imageRow <= boundingBox.MaxY &&
                                               imageRow >= boundingBox.MinY; imageRow += increment)
       {
          Codeword codeword = detectCodeword(image, 0, image.Width, leftToRight, startColumn, imageRow,
                                             minCodewordWidth, maxCodewordWidth);
          if (codeword != null)
          {
             rowIndicatorColumn.setCodeword(imageRow, codeword);
             if (leftToRight)
             {
                startColumn = codeword.StartX;
             }
             else
             {
                startColumn = codeword.EndX;
             }
          }
       }
    }
    return rowIndicatorColumn;
 }
 /// <summary>
 /// Gets the minimum width of the barcode
 /// </summary>
 /// <returns>The minimum width.</returns>
 /// <param name="p1">P1.</param>
 /// <param name="p2">P2.</param>
 private static int GetMinWidth(ResultPoint p1, ResultPoint p2)
 {
     if (p1 == null || p2 == null)
     {
         return int.MaxValue;
     }
     return (int)Math.Abs(p1.X - p2.X);
 }
Exemple #46
0
 /// <summary> <p>Estimates module size based on two finder patterns -- it uses
 /// {@link #sizeOfBlackWhiteBlackRunBothWays(int, int, int, int)} to figure the
 /// width of each, measuring along the axis between their centers.</p>
 /// </summary>
 private float calculateModuleSizeOneWay(ResultPoint pattern, ResultPoint otherPattern)
 {
    //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
    float moduleSizeEst1 = sizeOfBlackWhiteBlackRunBothWays((int)pattern.X, (int)pattern.Y, (int)otherPattern.X, (int)otherPattern.Y);
    //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
    float moduleSizeEst2 = sizeOfBlackWhiteBlackRunBothWays((int)otherPattern.X, (int)otherPattern.Y, (int)pattern.X, (int)pattern.Y);
    if (Single.IsNaN(moduleSizeEst1))
    {
       return moduleSizeEst2 / 7.0f;
    }
    if (Single.IsNaN(moduleSizeEst2))
    {
       return moduleSizeEst1 / 7.0f;
    }
    // Average them, and divide by 7 since we've counted the width of 3 black modules,
    // and 1 white and 1 black module on either side. Ergo, divide sum by 14.
    return (moduleSizeEst1 + moduleSizeEst2) / 14.0f;
 }
Exemple #47
0
 /// <summary> <p>Computes an average estimated module size based on estimated derived from the positions
 /// of the three finder patterns.</p>
 /// </summary>
 protected internal virtual float calculateModuleSize(ResultPoint topLeft, ResultPoint topRight, ResultPoint bottomLeft)
 {
    // Take the average
    return (calculateModuleSizeOneWay(topLeft, topRight) + calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0f;
 }
Exemple #48
0
 private void drawLine(Canvas canvas, Paint paint, ResultPoint a, ResultPoint b)
 {
     canvas.DrawLine(a.X, a.Y, b.X, b.Y, paint);
 }
Exemple #49
0
        /// <summary>
        /// Locate the vertices and the codewords area of a black blob using the Start and Stop patterns as locators.
        /// </summary>
        /// <param name="matrix">Matrix.</param>
        /// <param name="startRow">Start row.</param>
        /// <param name="startColumn">Start column.</param>
        /// <returns> an array containing the vertices:
        ///           vertices[0] x, y top left barcode
        ///           vertices[1] x, y bottom left barcode
        ///           vertices[2] x, y top right barcode
        ///           vertices[3] x, y bottom right barcode
        ///           vertices[4] x, y top left codeword area
        ///           vertices[5] x, y bottom left codeword area
        ///           vertices[6] x, y top right codeword area
        ///           vertices[7] x, y bottom right codeword area
        /// </returns>
        private static ResultPoint[] FindVertices(BitMatrix matrix, int startRow, int startColumn) {
            int height = matrix.Height;
            int width = matrix.Width;

            ResultPoint[] result = new ResultPoint[8];
            CopyToResult(result, FindRowsWithPattern(matrix, height, width, startRow, startColumn, START_PATTERN),
                         INDEXES_START_PATTERN);
            
            if (result[4] != null) {
                startColumn = (int) result[4].X;
                startRow = (int) result[4].Y;
            }
            CopyToResult(result, FindRowsWithPattern(matrix, height, width, startRow, startColumn, STOP_PATTERN),
                         INDEXES_STOP_PATTERN);
            return result;
        }
 private static Result translateResultPoints(Result result, int xOffset, int yOffset)
 {
    ResultPoint[] oldResultPoints = result.ResultPoints;
    ResultPoint[] newResultPoints = new ResultPoint[oldResultPoints.Length];
    for (int i = 0; i < oldResultPoints.Length; i++)
    {
       ResultPoint oldPoint = oldResultPoints[i];
       newResultPoints[i] = new ResultPoint(oldPoint.X + xOffset, oldPoint.Y + yOffset);
    }
    return new Result(result.Text, result.RawBytes, newResultPoints, result.BarcodeFormat);
 }
Exemple #51
0
 /// <summary>
 /// Finds the rows with the given pattern.
 /// </summary>
 /// <returns>The rows with pattern.</returns>
 /// <param name="matrix">Matrix.</param>
 /// <param name="height">Height.</param>
 /// <param name="width">Width.</param>
 /// <param name="startRow">Start row.</param>
 /// <param name="startColumn">Start column.</param>
 /// <param name="pattern">Pattern.</param>
 private static ResultPoint[] FindRowsWithPattern(
     BitMatrix matrix,
     int height,
     int width,
     int startRow,
     int startColumn,
     int[] pattern) {
     ResultPoint[] result = new ResultPoint[4];
     bool found = false;
     int[] counters = new int[pattern.Length];
     for (; startRow < height; startRow += ROW_STEP) {
         int[] loc = FindGuardPattern(matrix, startColumn, startRow, width, false, pattern, counters);
         if (loc != null) {
             while (startRow > 0) {
                 int[] previousRowLoc = FindGuardPattern(matrix, startColumn, --startRow, width, false, pattern, counters);
                 if (previousRowLoc != null) {
                     loc = previousRowLoc;
                 } else {
                     startRow++;
                     break;
                 }
             }
             result[0] = new ResultPoint(loc[0], startRow);
             result[1] = new ResultPoint(loc[1], startRow);
             found = true;
             break;
         }
     }
     int stopRow = startRow + 1;
     // Last row of the current symbol that contains pattern
     if (found) {
         int skippedRowCount = 0;
         int[] previousRowLoc = {(int) result[0].X, (int) result[1].X};
         for (; stopRow < height; stopRow++) {
             int[] loc = FindGuardPattern(matrix, previousRowLoc[0], stopRow, width, false, pattern, counters);
             // a found pattern is only considered to belong to the same barcode if the start and end positions
             // don't differ too much. Pattern drift should be not bigger than two for consecutive rows. With
             // a higher number of skipped rows drift could be larger. To keep it simple for now, we allow a slightly
             // larger drift and don't check for skipped rows.
             if (loc != null &&
                 Math.Abs(previousRowLoc[0] - loc[0]) < MAX_PATTERN_DRIFT &&
                 Math.Abs(previousRowLoc[1] - loc[1]) < MAX_PATTERN_DRIFT) {
                 previousRowLoc = loc;
                 skippedRowCount = 0;
             } else {
                 if (skippedRowCount > SKIPPED_ROW_COUNT_MAX) {
                     break;
                 } else {
                     skippedRowCount++;
                 }
             }
         }
         stopRow -= skippedRowCount + 1;
         result[2] = new ResultPoint(previousRowLoc[0], stopRow);
         result[3] = new ResultPoint(previousRowLoc[1], stopRow);
     }
     if (stopRow - startRow < BARCODE_MIN_HEIGHT) {
         for (int i = 0; i < result.Length; i++) {
             result[i] = null;
         }
     }
     return result;
 }
Exemple #52
0
 public ResultPointsAndTransitions(ResultPoint from, ResultPoint to, int transitions)
 {
     this.from        = from;
     this.to          = to;
     this.transitions = transitions;
 }
 /// <summary>
 /// If we adjust the width, set a new right corner coordinate and recalculate
 /// </summary>
 /// <param name="bottomRight">Bottom right.</param>
 internal void SetBottomRight(ResultPoint bottomRight)
 {
     this.BottomRight = bottomRight;
     calculateMinMaxValues();
 }
Exemple #54
0
      /// <summary>
      /// Processes the finder pattern info.
      /// </summary>
      /// <param name="info">The info.</param>
      /// <returns></returns>
      protected internal virtual DetectorResult processFinderPatternInfo(FinderPatternInfo info)
      {
         FinderPattern topLeft = info.TopLeft;
         FinderPattern topRight = info.TopRight;
         FinderPattern bottomLeft = info.BottomLeft;

         float moduleSize = calculateModuleSize(topLeft, topRight, bottomLeft);
         if (moduleSize < 1.0f)
         {
            return null;
         }
         int dimension;
         if (!computeDimension(topLeft, topRight, bottomLeft, moduleSize, out dimension))
            return null;
         Internal.Version provisionalVersion = Internal.Version.getProvisionalVersionForDimension(dimension);
         if (provisionalVersion == null)
            return null;
         int modulesBetweenFPCenters = provisionalVersion.DimensionForVersion - 7;

         AlignmentPattern alignmentPattern = null;
         // Anything above version 1 has an alignment pattern
         if (provisionalVersion.AlignmentPatternCenters.Length > 0)
         {

            // Guess where a "bottom right" finder pattern would have been
            float bottomRightX = topRight.X - topLeft.X + bottomLeft.X;
            float bottomRightY = topRight.Y - topLeft.Y + bottomLeft.Y;

            // Estimate that alignment pattern is closer by 3 modules
            // from "bottom right" to known top left location
            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            float correctionToTopLeft = 1.0f - 3.0f / (float)modulesBetweenFPCenters;
            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            int estAlignmentX = (int)(topLeft.X + correctionToTopLeft * (bottomRightX - topLeft.X));
            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            int estAlignmentY = (int)(topLeft.Y + correctionToTopLeft * (bottomRightY - topLeft.Y));

            // Kind of arbitrary -- expand search radius before giving up
            for (int i = 4; i <= 16; i <<= 1)
            {
               alignmentPattern = findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, (float)i);
               if (alignmentPattern == null)
                  continue;
               break;
            }
            // If we didn't find alignment pattern... well try anyway without it
         }

         PerspectiveTransform transform = createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension);

         BitMatrix bits = sampleGrid(image, transform, dimension);
         if (bits == null)
            return null;

         ResultPoint[] points;
         if (alignmentPattern == null)
         {
            points = new ResultPoint[] { bottomLeft, topLeft, topRight };
         }
         else
         {
            points = new ResultPoint[] { bottomLeft, topLeft, topRight, alignmentPattern };
         }
         return new DetectorResult(bits, points);
      }
      /// <summary>
      /// Decode the specified image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight, minCodewordWidth
      /// and maxCodewordWidth.
      /// TODO: don't pass in minCodewordWidth and maxCodewordWidth, pass in barcode columns for start and stop pattern
      /// columns. That way width can be deducted from the pattern column.
      /// This approach also allows to detect more details about the barcode, e.g. if a bar type (white or black) is wider 
      /// than it should be. This can happen if the scanner used a bad blackpoint.
      /// </summary>
      /// <param name="image">Image.</param>
      /// <param name="imageTopLeft">Image top left.</param>
      /// <param name="imageBottomLeft">Image bottom left.</param>
      /// <param name="imageTopRight">Image top right.</param>
      /// <param name="imageBottomRight">Image bottom right.</param>
      /// <param name="minCodewordWidth">Minimum codeword width.</param>
      /// <param name="maxCodewordWidth">Max codeword width.</param>
      public static DecoderResult decode(BitMatrix image,
                                         ResultPoint imageTopLeft,
                                         ResultPoint imageBottomLeft,
                                         ResultPoint imageTopRight,
                                         ResultPoint imageBottomRight,
                                         int minCodewordWidth,
                                         int maxCodewordWidth)
      {
         BoundingBox boundingBox = BoundingBox.Create(image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight);
         if (boundingBox == null)
            return null;

         DetectionResultRowIndicatorColumn leftRowIndicatorColumn = null;
         DetectionResultRowIndicatorColumn rightRowIndicatorColumn = null;
         DetectionResult detectionResult = null;
         for (int i = 0; i < 2; i++)
         {
            if (imageTopLeft != null)
            {
               leftRowIndicatorColumn = getRowIndicatorColumn(image, boundingBox, imageTopLeft, true, minCodewordWidth, maxCodewordWidth);
            }
            if (imageTopRight != null)
            {
               rightRowIndicatorColumn = getRowIndicatorColumn(image, boundingBox, imageTopRight, false, minCodewordWidth, maxCodewordWidth);
            }
            detectionResult = merge(leftRowIndicatorColumn, rightRowIndicatorColumn);
            if (detectionResult == null)
            {
               // TODO Based on Owen's Comments in <see cref="ZXing.ReaderException"/>, this method has been modified to continue silently
               // if a barcode was not decoded where it was detected instead of throwing a new exception object.
               return null;
            }
            if (i == 0 && detectionResult.Box != null &&
                (detectionResult.Box.MinY < boundingBox.MinY || detectionResult.Box.MaxY > boundingBox.MaxY))
            {
               boundingBox = detectionResult.Box;
            }
            else
            {
               detectionResult.Box = boundingBox;
               break;
            }
         }
         int maxBarcodeColumn = detectionResult.ColumnCount + 1;
         detectionResult.DetectionResultColumns[0] = leftRowIndicatorColumn;

         detectionResult.DetectionResultColumns[maxBarcodeColumn] = rightRowIndicatorColumn;

         bool leftToRight = leftRowIndicatorColumn != null;
         for (int barcodeColumnCount = 1; barcodeColumnCount <= maxBarcodeColumn; barcodeColumnCount++)
         {
            int barcodeColumn = leftToRight ? barcodeColumnCount : maxBarcodeColumn - barcodeColumnCount;
            if (detectionResult.DetectionResultColumns[barcodeColumn] != null)
            {
               // This will be the case for the opposite row indicator column, which doesn't need to be decoded again.
               continue;
            }
            DetectionResultColumn detectionResultColumn;
            if (barcodeColumn == 0 || barcodeColumn == maxBarcodeColumn)
            {
               detectionResultColumn = new DetectionResultRowIndicatorColumn(boundingBox, barcodeColumn == 0);
            }
            else
            {
               detectionResultColumn = new DetectionResultColumn(boundingBox);
            }
            detectionResult.DetectionResultColumns[barcodeColumn] = detectionResultColumn;
            int startColumn = -1;
            int previousStartColumn = startColumn;
            // TODO start at a row for which we know the start position, then detect upwards and downwards from there.
            for (int imageRow = boundingBox.MinY; imageRow <= boundingBox.MaxY; imageRow++)
            {
               startColumn = getStartColumn(detectionResult, barcodeColumn, imageRow, leftToRight);
               if (startColumn < 0 || startColumn > boundingBox.MaxX)
               {
                  if (previousStartColumn == -1)
                  {
                     continue;
                  }
                  startColumn = previousStartColumn;
               }
               Codeword codeword = detectCodeword(image, boundingBox.MinX, boundingBox.MaxX, leftToRight,
                                                  startColumn, imageRow, minCodewordWidth, maxCodewordWidth);
               if (codeword != null)
               {
                  detectionResultColumn.setCodeword(imageRow, codeword);
                  previousStartColumn = startColumn;
                  minCodewordWidth = Math.Min(minCodewordWidth, codeword.Width);
                  maxCodewordWidth = Math.Max(maxCodewordWidth, codeword.Width);
               }
            }
         }
         return createDecoderResult(detectionResult);
      }
 /// <summary>
 /// If we adjust the width, set a new right corner coordinate and recalculate
 /// </summary>
 /// <param name="topRight">Top right.</param>
 internal void SetTopRight(ResultPoint topRight)
 {
     this.TopRight = topRight;
     CalculateMinMaxValues();
 }
Exemple #57
0
      /// <summary>
      /// We're going to examine rows from the middle outward, searching alternately above and below the
      /// middle, and farther out each time. rowStep is the number of rows between each successive
      /// attempt above and below the middle. So we'd scan row middle, then middle - rowStep, then
      /// middle + rowStep, then middle - (2 * rowStep), etc.
      /// rowStep is bigger as the image is taller, but is always at least 1. We've somewhat arbitrarily
      /// decided that moving up and down by about 1/16 of the image is pretty good; we try more of the
      /// image if "trying harder".
      /// </summary>
      /// <param name="image">The image to decode</param>
      /// <param name="hints">Any hints that were requested</param>
      /// <returns>The contents of the decoded barcode</returns>
      virtual protected Result doDecode(BinaryBitmap image, IDictionary<DecodeHintType, object> hints)
      {
         int width = image.Width;
         int height = image.Height;
         BitArray row = new BitArray(width);

         int middle = height >> 1;
         bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER);
         int rowStep = Math.Max(1, height >> (tryHarder ? 8 : 5));
         int maxLines;
         if (tryHarder)
         {
            maxLines = height; // Look at the whole image, not just the center
         }
         else
         {
            maxLines = 15; // 15 rows spaced 1/32 apart is roughly the middle half of the image
         }

         for (int x = 0; x < maxLines; x++)
         {

            // Scanning from the middle out. Determine which row we're looking at next:
            int rowStepsAboveOrBelow = (x + 1) >> 1;
            bool isAbove = (x & 0x01) == 0; // i.e. is x even?
            int rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow);
            if (rowNumber < 0 || rowNumber >= height)
            {
               // Oops, if we run off the top or bottom, stop
               break;
            }

            // Estimate black point for this row and load it:
            row = image.getBlackRow(rowNumber, row);
            if (row == null)
               continue;

            // While we have the image data in a BitArray, it's fairly cheap to reverse it in place to
            // handle decoding upside down barcodes.
            for (int attempt = 0; attempt < 2; attempt++)
            {
               if (attempt == 1)
               { 
                  // trying again?
                  row.reverse(); // reverse the row and continue
                  // This means we will only ever draw result points *once* in the life of this method
                  // since we want to avoid drawing the wrong points after flipping the row, and,
                  // don't want to clutter with noise from every single row scan -- just the scans
                  // that start on the center line.
                  if (hints != null && hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK))
                  {
                     IDictionary<DecodeHintType, Object> newHints = new Dictionary<DecodeHintType, Object>();
                     foreach (var hint in hints)
                     {
                        if (hint.Key != DecodeHintType.NEED_RESULT_POINT_CALLBACK)
                           newHints.Add(hint.Key, hint.Value);
                     }
                     hints = newHints;
                  }
               }
               // Look for a barcode
               Result result = decodeRow(rowNumber, row, hints);
               if (result == null)
                  continue;

               // We found our barcode
               if (attempt == 1)
               {
                  // But it was upside down, so note that
                  result.putMetadata(ResultMetadataType.ORIENTATION, 180);
                  // And remember to flip the result points horizontally.
                  ResultPoint[] points = result.ResultPoints;
                  if (points != null)
                  {
                     points[0] = new ResultPoint(width - points[0].X - 1, points[0].Y);
                     points[1] = new ResultPoint(width - points[1].X - 1, points[1].Y);
                  }
               }
               return result;
            }
         }

         return null;
      }
Exemple #58
0
 /// <summary>
 /// Copies the temp data to the final result
 /// </summary>
 /// <param name="result">Result.</param>
 /// <param name="tmpResult">Temp result.</param>
 /// <param name="destinationIndexes">Destination indexes.</param>
 private static void CopyToResult(ResultPoint[] result, ResultPoint[] tmpResult, int[] destinationIndexes) {
     for (int i = 0; i < destinationIndexes.Length; i++) {
         result[destinationIndexes[i]] = tmpResult[i];
     }
 }
Exemple #59
0
        /**
         * <p>Detects a Data Matrix Code in an image.</p>
         *
         * @return {@link DetectorResult} encapsulating results of detecting a QR Code
         * @throws ReaderException if no Data Matrix Code can be found
         */
        public DetectorResult detect()
        {
            if (!BlackPointEstimationMethod.TWO_D_SAMPLING.Equals(image.getLastEstimationMethod()))
            {
                image.estimateBlackPoint(BlackPointEstimationMethod.TWO_D_SAMPLING, 0);
            }

            int height     = image.getHeight();
            int width      = image.getWidth();
            int halfHeight = height >> 1;
            int halfWidth  = width >> 1;
            int iSkip      = Math.Max(1, height / (MAX_MODULES << 3));
            int jSkip      = Math.Max(1, width / (MAX_MODULES << 3));

            int         minI   = 0;
            int         maxI   = height;
            int         minJ   = 0;
            int         maxJ   = width;
            ResultPoint pointA = findCornerFromCenter(halfHeight, -iSkip, minI, maxI, halfWidth, 0, minJ, maxJ, halfWidth >> 1);

            minI = (int)pointA.getY() - 1;
            ResultPoint pointB = findCornerFromCenter(halfHeight, 0, minI, maxI, halfWidth, -jSkip, minJ, maxJ, halfHeight >> 1);

            minJ = (int)pointB.getX() - 1;
            ResultPoint pointC = findCornerFromCenter(halfHeight, 0, minI, maxI, halfWidth, jSkip, minJ, maxJ, halfHeight >> 1);

            maxJ = (int)pointC.getX() + 1;
            ResultPoint pointD = findCornerFromCenter(halfHeight, iSkip, minI, maxI, halfWidth, 0, minJ, maxJ, halfWidth >> 1);

            maxI = (int)pointD.getY() + 1;
            // Go try to find point A again with better information -- might have been off at first.
            pointA = findCornerFromCenter(halfHeight, -iSkip, minI, maxI, halfWidth, 0, minJ, maxJ, halfWidth >> 2);

            // Point A and D are across the diagonal from one another,
            // as are B and C. Figure out which are the solid black lines
            // by counting transitions
            System.Collections.ArrayList transitions = new System.Collections.ArrayList(4);
            transitions.Add(transitionsBetween(pointA, pointB));
            transitions.Add(transitionsBetween(pointA, pointC));
            transitions.Add(transitionsBetween(pointB, pointD));
            transitions.Add(transitionsBetween(pointC, pointD));
            Collections.insertionSort(transitions, new ResultPointsAndTransitionsComparator());

            // Sort by number of transitions. First two will be the two solid sides; last two
            // will be the two alternating black/white sides
            ResultPointsAndTransitions lSideOne = (ResultPointsAndTransitions)transitions[0];
            ResultPointsAndTransitions lSideTwo = (ResultPointsAndTransitions)transitions[1];

            // Figure out which point is their intersection by tallying up the number of times we see the
            // endpoints in the four endpoints. One will show up twice.
            System.Collections.Hashtable pointCount = new System.Collections.Hashtable();
            increment(pointCount, lSideOne.getFrom());
            increment(pointCount, lSideOne.getTo());
            increment(pointCount, lSideTwo.getFrom());
            increment(pointCount, lSideTwo.getTo());

            ResultPoint maybeTopLeft     = null;
            ResultPoint bottomLeft       = null;
            ResultPoint maybeBottomRight = null;

            System.Collections.IEnumerator points = pointCount.GetEnumerator();

            while (points.MoveNext())
            {
                ResultPoint point = (ResultPoint)points.Current;
                int         value = (int)pointCount[point];
                if (value == 2)
                {
                    bottomLeft = point; // this is definitely the bottom left, then -- end of two L sides
                }
                else
                {
                    // Otherwise it's either top left or bottom right -- just assign the two arbitrarily now
                    if (maybeTopLeft == null)
                    {
                        maybeTopLeft = point;
                    }
                    else
                    {
                        maybeBottomRight = point;
                    }
                }
            }

            if (maybeTopLeft == null || bottomLeft == null || maybeBottomRight == null)
            {
                throw new ReaderException();
            }

            // Bottom left is correct but top left and bottom right might be switched
            ResultPoint[] corners = { maybeTopLeft, bottomLeft, maybeBottomRight };
            // Use the dot product trick to sort them out
            GenericResultPoint.orderBestPatterns(corners);

            // Now we know which is which:
            ResultPoint bottomRight = corners[0];

            bottomLeft = corners[1];
            ResultPoint topLeft = corners[2];

            // Which point didn't we find in relation to the "L" sides? that's the top right corner
            ResultPoint topRight;

            if (!pointCount.ContainsKey(pointA))
            {
                topRight = pointA;
            }
            else if (!pointCount.ContainsKey(pointB))
            {
                topRight = pointB;
            }
            else if (!pointCount.ContainsKey(pointC))
            {
                topRight = pointC;
            }
            else
            {
                topRight = pointD;
            }

            // Next determine the dimension by tracing along the top or right side and counting black/white
            // transitions. Since we start inside a black module, we should see a number of transitions
            // equal to 1 less than the code dimension. Well, actually 2 less, because we are going to
            // end on a black module:

            // The top right point is actually the corner of a module, which is one of the two black modules
            // adjacent to the white module at the top right. Tracing to that corner from either the top left
            // or bottom right should work here, but, one will be more reliable since it's traced straight
            // up or across, rather than at a slight angle. We use dot products to figure out which is
            // better to use:
            int dimension;

            if (GenericResultPoint.crossProductZ(bottomLeft, bottomRight, topRight) <
                GenericResultPoint.crossProductZ(topRight, topLeft, bottomLeft))
            {
                dimension = transitionsBetween(topLeft, topRight).getTransitions();
            }
            else
            {
                dimension = transitionsBetween(bottomRight, topRight).getTransitions();
            }
            dimension += 2;

            BitMatrix bits = sampleGrid(image, topLeft, bottomLeft, bottomRight, dimension);

            return(new DetectorResult(bits, new ResultPoint[] { pointA, pointB, pointC, pointD }));
        }
Exemple #60
0
 /// <summary>
 /// Locates and decodes a barcode in some format within an image. This method also accepts
 /// hints, each possibly associated to some data, which may help the implementation decode.
 /// Note that we don't try rotation without the try harder flag, even if rotation was supported.
 /// </summary>
 /// <param name="image">image of barcode to decode</param>
 /// <param name="hints">passed as a <see cref="IDictionary{TKey, TValue}"/> from <see cref="DecodeHintType"/>
 /// to arbitrary data. The
 /// meaning of the data depends upon the hint type. The implementation may or may not do
 /// anything with these hints.</param>
 /// <returns>
 /// String which the barcode encodes
 /// </returns>
 virtual public Result decode(BinaryBitmap image, IDictionary<DecodeHintType, object> hints)
 {
    var result = doDecode(image, hints);
    if (result == null)
    {
       bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER);
       bool tryHarderWithoutRotation = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER_WITHOUT_ROTATION);
       if (tryHarder && !tryHarderWithoutRotation && image.RotateSupported)
       {
          BinaryBitmap rotatedImage = image.rotateCounterClockwise();
          result = doDecode(rotatedImage, hints);
          if (result == null)
             return null;
          // Record that we found it rotated 90 degrees CCW / 270 degrees CW
          IDictionary<ResultMetadataType, object> metadata = result.ResultMetadata;
          int orientation = 270;
          if (metadata != null && metadata.ContainsKey(ResultMetadataType.ORIENTATION))
          {
             // But if we found it reversed in doDecode(), add in that result here:
             orientation = (orientation +
                            (int) metadata[ResultMetadataType.ORIENTATION])%360;
          }
          result.putMetadata(ResultMetadataType.ORIENTATION, orientation);
          // Update result points
          ResultPoint[] points = result.ResultPoints;
          if (points != null)
          {
             int height = rotatedImage.Height;
             for (int i = 0; i < points.Length; i++)
             {
                points[i] = new ResultPoint(height - points[i].Y - 1, points[i].X);
             }
          }
       }
    }
    return result;
 }