/// <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.Generic.List <Object> transitions = new System.Collections.Generic.List <Object>(4); //GregBray: Removed Synchronized wrapper 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.Generic.Dictionary <Object, Object> pointCount = new System.Collections.Generic.Dictionary <Object, Object>(); 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 })); }
/** * <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 })); }
/// <summary> /// <p>Detects a Data Matrix Code in an image.</p> /// </summary> /// <returns> <seealso cref="DetectorResult"/> encapsulating results of detecting a Data Matrix Code </returns> /// <exception cref="NotFoundException"> if no Data Matrix Code can be found </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public com.google.zxing.common.DetectorResult detect() throws com.google.zxing.NotFoundException 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 List <ResultPointsAndTransitions> transitions = new List <ResultPointsAndTransitions>(4); transitions.Add(transitionsBetween(pointA, pointB)); transitions.Add(transitionsBetween(pointA, pointC)); transitions.Add(transitionsBetween(pointB, pointD)); transitions.Add(transitionsBetween(pointC, pointD)); transitions.Sort(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 = transitions[0]; ResultPointsAndTransitions lSideTwo = 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. IDictionary <ResultPoint, int?> pointCount = new Dictionary <ResultPoint, int?>(); 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; foreach (KeyValuePair <ResultPoint, int?> entry in pointCount) { ResultPoint point = entry.Key; int? value = entry.Value; 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 NotFoundException.NotFoundInstance; } // 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 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. int dimensionTop = transitionsBetween(topLeft, topRight).Transitions; int dimensionRight = transitionsBetween(bottomRight, topRight).Transitions; if ((dimensionTop & 0x01) == 1) { // it can't be odd, so, round... up? dimensionTop++; } dimensionTop += 2; if ((dimensionRight & 0x01) == 1) { // it can't be odd, so, round... up? dimensionRight++; } dimensionRight += 2; BitMatrix bits; ResultPoint correctedTopRight; // Rectanguar symbols are 6x16, 6x28, 10x24, 10x32, 14x32, or 14x44. If one dimension is more // than twice the other, it's certainly rectangular, but to cut a bit more slack we accept it as // rectangular if the bigger side is at least 7/4 times the other: if (4 * dimensionTop >= 7 * dimensionRight || 4 * dimensionRight >= 7 * dimensionTop) { // The matrix is rectangular correctedTopRight = correctTopRightRectangular(bottomLeft, bottomRight, topLeft, topRight, dimensionTop, dimensionRight); if (correctedTopRight == null) { correctedTopRight = topRight; } dimensionTop = transitionsBetween(topLeft, correctedTopRight).Transitions; dimensionRight = transitionsBetween(bottomRight, correctedTopRight).Transitions; if ((dimensionTop & 0x01) == 1) { // it can't be odd, so, round... up? dimensionTop++; } if ((dimensionRight & 0x01) == 1) { // it can't be odd, so, round... up? dimensionRight++; } bits = sampleGrid(image, topLeft, bottomLeft, bottomRight, correctedTopRight, dimensionTop, dimensionRight); } else { // The matrix is square int dimension = Math.Min(dimensionRight, dimensionTop); // correct top right point to match the white module correctedTopRight = correctTopRight(bottomLeft, bottomRight, topLeft, topRight, dimension); if (correctedTopRight == null) { correctedTopRight = topRight; } // Redetermine the dimension using the corrected top right point int dimensionCorrected = Math.Max(transitionsBetween(topLeft, correctedTopRight).Transitions, transitionsBetween(bottomRight, correctedTopRight).Transitions); dimensionCorrected++; if ((dimensionCorrected & 0x01) == 1) { dimensionCorrected++; } bits = sampleGrid(image, topLeft, bottomLeft, bottomRight, correctedTopRight, dimensionCorrected, dimensionCorrected); } return(new DetectorResult(bits, new ResultPoint[] { topLeft, bottomLeft, bottomRight, correctedTopRight })); }