예제 #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;
        }
예제 #2
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;
        }
 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);
 }
예제 #4
0
        private static BitMatrix sampleGrid(BitMatrix matrix, ResultPoint topLeft, ResultPoint bottomLeft, ResultPoint topRight, ResultPoint bottomRight, int dimension)
        {
            // Note that unlike 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(matrix, dimension, 0.0f, 0.0f, dimension, 0.0f, dimension, dimension, 0.0f, dimension, topLeft.X, topLeft.Y, topRight.X, topRight.Y, bottomRight.X, bottomRight.Y, bottomLeft.X, bottomLeft.Y); // p4FromY
        }
예제 #5
0
        /// <summary> Locate the vertices and the codewords area of a black blob using the Start
        /// and Stop patterns as locators. This assumes that the image is rotated 180
        /// degrees and if it locates the start and stop patterns at it will re-map
        /// the vertices for a 0 degree rotation.
        /// TODO: Change assumption about barcode location.
        /// TODO: Scanning every row is very expensive. We should only do this for TRY_HARDER.
        /// 
        /// </summary>
        /// <param name="matrix">the scanned barcode image.
        /// </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[] findVertices180(BitMatrix matrix)
        {
            int height = matrix.Height;
            int width = matrix.Width;
            int halfWidth = width >> 1;

            ResultPoint[] result = new ResultPoint[8];
            bool found = false;

            // Top Left
            for (int i = height - 1; i > 0; i--)
            {
                int[] loc = findGuardPattern(matrix, halfWidth, i, halfWidth, true, START_PATTERN_REVERSE);
                if (loc != null)
                {
                    result[0] = new ResultPoint(loc[1], i);
                    result[4] = new ResultPoint(loc[0], i);
                    found = true;
                    break;
                }
            }
            // Bottom Left
            if (found)
            {
                // Found the Top Left vertex
                found = false;
                for (int i = 0; i < height; i++)
                {
                    int[] loc = findGuardPattern(matrix, halfWidth, i, halfWidth, true, START_PATTERN_REVERSE);
                    if (loc != null)
                    {
                        result[1] = new ResultPoint(loc[1], i);
                        result[5] = new ResultPoint(loc[0], i);
                        found = true;
                        break;
                    }
                }
            }
            // Top Right
            if (found)
            {
                // Found the Bottom Left vertex
                found = false;
                for (int i = height - 1; i > 0; i--)
                {
                    int[] loc = findGuardPattern(matrix, 0, i, halfWidth, false, STOP_PATTERN_REVERSE);
                    if (loc != null)
                    {
                        result[2] = new ResultPoint(loc[0], i);
                        result[6] = new ResultPoint(loc[1], i);
                        found = true;
                        break;
                    }
                }
            }
            // Bottom Right
            if (found)
            {
                // Found the Top Right vertex
                found = false;
                for (int i = 0; i < height; i++)
                {
                    int[] loc = findGuardPattern(matrix, 0, i, halfWidth, false, STOP_PATTERN_REVERSE);
                    if (loc != null)
                    {
                        result[3] = new ResultPoint(loc[0], i);
                        result[7] = new ResultPoint(loc[1], i);
                        found = true;
                        break;
                    }
                }
            }
            return found?result:null;
        }
예제 #6
0
        /// <summary> Because we scan horizontally to detect the start and stop patterns, the vertical component of
        /// the codeword coordinates will be slightly wrong if there is any skew or rotation in the image.
        /// This method moves those points back onto the edges of the theoretically perfect bounding
        /// quadrilateral if needed.
        /// 
        /// </summary>
        /// <param name="vertices">The eight vertices located by findVertices().
        /// </param>
        private static void correctCodeWordVertices(ResultPoint[] vertices, bool upsideDown)
        {
            float skew = vertices[4].Y - vertices[6].Y;
            if (upsideDown)
            {
                skew = - skew;
            }
            if (skew > SKEW_THRESHOLD)
            {
                // Fix v4
                float length = vertices[4].X - vertices[0].X;
                float deltax = vertices[6].X - vertices[0].X;
                float deltay = vertices[6].Y - vertices[0].Y;
                float correction = length * deltay / deltax;
                vertices[4] = new ResultPoint(vertices[4].X, vertices[4].Y + correction);
            }
            else if (- skew > SKEW_THRESHOLD)
            {
                // Fix v6
                float length = vertices[2].X - vertices[6].X;
                float deltax = vertices[2].X - vertices[4].X;
                float deltay = vertices[2].Y - vertices[4].Y;
                float correction = length * deltay / deltax;
                vertices[6] = new ResultPoint(vertices[6].X, vertices[6].Y - correction);
            }

            skew = vertices[7].Y - vertices[5].Y;
            if (upsideDown)
            {
                skew = - skew;
            }
            if (skew > SKEW_THRESHOLD)
            {
                // Fix v5
                float length = vertices[5].X - vertices[1].X;
                float deltax = vertices[7].X - vertices[1].X;
                float deltay = vertices[7].Y - vertices[1].Y;
                float correction = length * deltay / deltax;
                vertices[5] = new ResultPoint(vertices[5].X, vertices[5].Y + correction);
            }
            else if (- skew > SKEW_THRESHOLD)
            {
                // Fix v7
                float length = vertices[3].X - vertices[7].X;
                float deltax = vertices[3].X - vertices[5].X;
                float deltay = vertices[3].Y - vertices[5].Y;
                float correction = length * deltay / deltax;
                vertices[7] = new ResultPoint(vertices[7].X, vertices[7].Y - correction);
            }
        }
예제 #7
0
        private static BitMatrix sampleGrid(BitMatrix 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.X - bottomLeft.X) + topLeft.X;
            float topRightY = (bottomRight.Y - bottomLeft.Y) + topLeft.Y;

            // 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.X, topLeft.Y, topRightX, topRightY, bottomRight.X, bottomRight.Y, bottomLeft.X, bottomLeft.Y);
        }
예제 #8
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;
 }
예제 #9
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;
         }
     }
 }
예제 #10
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>
        /// <throws>  ReaderException Any spontaneous errors which occur </throws>
        private Result doDecode(BinaryBitmap image, System.Collections.Hashtable 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 = System.Math.Max(1, height >> (tryHarder?7:4));
            int maxLines;
            if (tryHarder)
            {
                maxLines = height; // Look at the whole image, not just the center
            }
            else
            {
                maxLines = 9; // Nine rows spaced 1/16 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:
                try
                {
                    row = image.getBlackRow(rowNumber, row);
                }
                catch (ReaderException)
                {
                    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))
                        {
                            System.Collections.Hashtable newHints = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable()); // Can't use clone() in J2ME
                            System.Collections.IEnumerator hintEnum = hints.Keys.GetEnumerator();
                            //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
                            while (hintEnum.MoveNext())
                            {
                                //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
                                System.Object key = hintEnum.Current;
                                if (!key.Equals(DecodeHintType.NEED_RESULT_POINT_CALLBACK))
                                {
                                    newHints[key] = hints[key];
                                }
                            }
                            hints = newHints;
                        }
                    }
                    try
                    {
                        // Look for a barcode
                        Result result = decodeRow(rowNumber, row, hints);
                        // We found our barcode
                        if (attempt == 1)
                        {
                            // But it was upside down, so note that
                            result.putMetadata(ResultMetadataType.ORIENTATION, (System.Object) 180);
                            // And remember to flip the result points horizontally.
                            ResultPoint[] points = result.ResultPoints;
                            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;
                    }
                    catch (ReaderException)
                    {
                        // continue -- just couldn't decode this row
                    }
                }
            }

            throw ReaderException.Instance;
        }
예제 #11
0
 public DetectorResult(BitMatrix bits, ResultPoint[] points)
 {
     this.bits = bits;
     this.points = points;
 }
예제 #12
0
        /// <summary> <p>Detects a Data Matrix Code in an image.</p>
        /// 
        /// </summary>
        /// <returns> {@link DetectorResult} encapsulating results of detecting a QR Code
        /// </returns>
        /// <throws>  ReaderException if no Data Matrix Code can be found </throws>
        public DetectorResult detect()
        {
            ResultPoint[] cornerPoints = rectangleDetector.detect();
            ResultPoint pointA = cornerPoints[0];
            ResultPoint pointB = cornerPoints[1];
            ResultPoint pointC = cornerPoints[2];
            ResultPoint pointD = cornerPoints[3];

            // 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 = System.Collections.ArrayList.Synchronized(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 = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable());
            increment(pointCount, lSideOne.From);
            increment(pointCount, lSideOne.To);
            increment(pointCount, lSideTwo.From);
            increment(pointCount, lSideTwo.To);

            ResultPoint maybeTopLeft = null;
            ResultPoint bottomLeft = null;
            ResultPoint maybeBottomRight = null;
            System.Collections.IEnumerator points = pointCount.Keys.GetEnumerator();
            //UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
            while (points.MoveNext())
            {
                //UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
                ResultPoint point = (ResultPoint) points.Current;
                System.Int32 value_Renamed = (System.Int32) pointCount[point];
                if (value_Renamed == 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 ReaderException.Instance;
            }

            // Bottom left is correct but top left and bottom right might be switched
            ResultPoint[] corners = new ResultPoint[]{maybeTopLeft, bottomLeft, maybeBottomRight};
            // Use the dot product trick to sort them out
            ResultPoint.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. The number of transitions could be higher than it should be
            // due to noise. So we try both and take the min.

            int dimension = System.Math.Min(transitionsBetween(topLeft, topRight).Transitions, transitionsBetween(bottomRight, topRight).Transitions);
            if ((dimension & 0x01) == 1)
            {
                // it can't be odd, so, round... up?
                dimension++;
            }
            dimension += 2;

            BitMatrix bits = sampleGrid(image, topLeft, bottomLeft, bottomRight, dimension);
            return new DetectorResult(bits, new ResultPoint[]{pointA, pointB, pointC, pointD});
        }
예제 #13
0
 internal ResultPointsAndTransitions(ResultPoint from, ResultPoint to, int transitions)
 {
     this.from = from;
     this.to = to;
     this.transitions = transitions;
 }
예제 #14
0
        /// <summary> Counts the number of black/white transitions between two points, using something like Bresenham's algorithm.</summary>
        private ResultPointsAndTransitions transitionsBetween(ResultPoint from, ResultPoint to)
        {
            // See QR Code Detector, sizeOfBlackWhiteBlackRun()
            //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 fromX = (int) from.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 fromY = (int) from.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'"
            int toX = (int) to.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 toY = (int) to.Y;
            bool steep = System.Math.Abs(toY - fromY) > System.Math.Abs(toX - fromX);
            if (steep)
            {
                int temp = fromX;
                fromX = fromY;
                fromY = temp;
                temp = toX;
                toX = toY;
                toY = temp;
            }

            int dx = System.Math.Abs(toX - fromX);
            int dy = System.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.get_Renamed(steep?fromY:fromX, steep?fromX:fromY);
            for (int x = fromX, y = fromY; x != toX; x += xstep)
            {
                bool isBlack = image.get_Renamed(steep?y:x, steep?x:y);
                if (isBlack != inBlack)
                {
                    transitions++;
                    inBlack = isBlack;
                }
                error += dy;
                if (error > 0)
                {
                    if (y == toY)
                    {
                        break;
                    }
                    y += ystep;
                    error -= dx;
                }
            }
            return new ResultPointsAndTransitions(from, to, transitions);
        }
예제 #15
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;
 }
예제 #16
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;

            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)
                {
                    try
                    {
                        //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'"
                        alignmentPattern = findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, (float) i);
                        break;
                    }
                    catch (ReaderException)
                    {
                        // try next round
                    }
                }
                // 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);

            ResultPoint[] points;
            if (alignmentPattern == null)
            {
                points = new ResultPoint[]{bottomLeft, topLeft, topRight};
            }
            else
            {
                points = new ResultPoint[]{bottomLeft, topLeft, topRight, alignmentPattern};
            }
            return new DetectorResult(bits, points);
        }
예제 #17
0
 /// <summary> Computes the dimension (number of modules in a row) of the PDF417 Code
 /// based on vertices of the codeword area and estimated module size.
 /// 
 /// </summary>
 /// <param name="topLeft">    of codeword area
 /// </param>
 /// <param name="topRight">   of codeword area
 /// </param>
 /// <param name="bottomLeft"> of codeword area
 /// </param>
 /// <param name="bottomRight">of codeword are
 /// </param>
 /// <param name="moduleWidth">estimated module size
 /// </param>
 /// <returns> the number of modules in a row.
 /// </returns>
 private static int computeDimension(ResultPoint topLeft, ResultPoint topRight, ResultPoint bottomLeft, ResultPoint bottomRight, float moduleWidth)
 {
     int topRowDimension = round(ResultPoint.distance(topLeft, topRight) / moduleWidth);
     int bottomRowDimension = round(ResultPoint.distance(bottomLeft, bottomRight) / moduleWidth);
     return ((((topRowDimension + bottomRowDimension) >> 1) + 8) / 17) * 17;
     /*
     * int topRowDimension = round(ResultPoint.distance(topLeft,
     * topRight)); //moduleWidth); int bottomRowDimension =
     * round(ResultPoint.distance(bottomLeft, bottomRight)); //
     * moduleWidth); int dimension = ((topRowDimension + bottomRowDimension)
     * >> 1); // Round up to nearest 17 modules i.e. there are 17 modules per
     * codeword //int dimension = ((((topRowDimension + bottomRowDimension) >>
     * 1) + 8) / 17) * 17; return dimension;
     */
 }
예제 #18
0
 /// <summary> <p>Estimates module size (pixels in a module) based on the Start and End
 /// finder patterns.</p>
 /// 
 /// </summary>
 /// <param name="vertices">an array of 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
 /// </param>
 /// <returns> the module size.
 /// </returns>
 private static float computeModuleWidth(ResultPoint[] vertices)
 {
     float pixels1 = ResultPoint.distance(vertices[0], vertices[4]);
     float pixels2 = ResultPoint.distance(vertices[1], vertices[5]);
     float moduleWidth1 = (pixels1 + pixels2) / (17 * 2.0f);
     float pixels3 = ResultPoint.distance(vertices[6], vertices[2]);
     float pixels4 = ResultPoint.distance(vertices[7], vertices[3]);
     float moduleWidth2 = (pixels3 + pixels4) / (18 * 2.0f);
     return (moduleWidth1 + moduleWidth2) / 2.0f;
 }
예제 #19
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
 }