/// <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); }
/// <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; */ }
/// <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); }
/// <returns> the 3 best {@link FinderPattern}s from our list of candidates. The "best" are /// those that have been detected at least {@link #CENTER_QUORUM} times, and whose module /// size differs from the average among those patterns the least /// </returns> /// <throws> ReaderException if 3 such finder patterns do not exist </throws> private FinderPattern[][] selectBestPatterns() { // System.Collections.ArrayList possibleCenters = PossibleCenters; // commented by .net follower (http://dotnetfollower.com) System.Collections.Generic.List <Object> possibleCenters = PossibleCenters; // added by .net follower (http://dotnetfollower.com) int size = possibleCenters.Count; if (size < 3) { // Couldn't find enough finder patterns throw ReaderException.Instance; } /* * Begin HE modifications to safely detect multiple codes of equal size */ if (size == 3) { return(new FinderPattern[][] { new FinderPattern[] { (FinderPattern)possibleCenters[0], (FinderPattern)possibleCenters[1], (FinderPattern)possibleCenters[2] } }); } // Sort by estimated module size to speed up the upcoming checks Collections.insertionSort(possibleCenters, new ModuleSizeComparator()); /* * Now lets start: build a list of tuples of three finder locations that * - feature similar module sizes * - are placed in a distance so the estimated module count is within the QR specification * - have similar distance between upper left/right and left top/bottom finder patterns * - form a triangle with 90° angle (checked by comparing top right/bottom left distance * with pythagoras) * * Note: we allow each point to be used for more than one code region: this might seem * counterintuitive at first, but the performance penalty is not that big. At this point, * we cannot make a good quality decision whether the three finders actually represent * a QR code, or are just by chance layouted so it looks like there might be a QR code there. * So, if the layout seems right, lets have the decoder try to decode. */ // System.Collections.ArrayList results = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10)); // holder for the results // commented by .net follower (http://dotnetfollower.com) System.Collections.Generic.List <Object> results = new System.Collections.Generic.List <Object>(10); // holder for the results // added by .net follower (http://dotnetfollower.com) for (int i1 = 0; i1 < (size - 2); i1++) { FinderPattern p1 = (FinderPattern)possibleCenters[i1]; if (p1 == null) { continue; } for (int i2 = i1 + 1; i2 < (size - 1); i2++) { FinderPattern p2 = (FinderPattern)possibleCenters[i2]; if (p2 == null) { continue; } // Compare the expected module sizes; if they are really off, skip float vModSize12 = (p1.EstimatedModuleSize - p2.EstimatedModuleSize) / (System.Math.Min(p1.EstimatedModuleSize, p2.EstimatedModuleSize)); float vModSize12A = System.Math.Abs(p1.EstimatedModuleSize - p2.EstimatedModuleSize); if (vModSize12A > DIFF_MODSIZE_CUTOFF && vModSize12 >= DIFF_MODSIZE_CUTOFF_PERCENT) { // break, since elements are ordered by the module size deviation there cannot be // any more interesting elements for the given p1. break; } for (int i3 = i2 + 1; i3 < size; i3++) { FinderPattern p3 = (FinderPattern)possibleCenters[i3]; if (p3 == null) { continue; } // Compare the expected module sizes; if they are really off, skip float vModSize23 = (p2.EstimatedModuleSize - p3.EstimatedModuleSize) / (System.Math.Min(p2.EstimatedModuleSize, p3.EstimatedModuleSize)); float vModSize23A = System.Math.Abs(p2.EstimatedModuleSize - p3.EstimatedModuleSize); if (vModSize23A > DIFF_MODSIZE_CUTOFF && vModSize23 >= DIFF_MODSIZE_CUTOFF_PERCENT) { // break, since elements are ordered by the module size deviation there cannot be // any more interesting elements for the given p1. break; } FinderPattern[] test = new FinderPattern[] { p1, p2, p3 }; ResultPoint.orderBestPatterns(test); // Calculate the distances: a = topleft-bottomleft, b=topleft-topright, c = diagonal FinderPatternInfo info = new FinderPatternInfo(test); float dA = ResultPoint.distance(info.TopLeft, info.BottomLeft); float dC = ResultPoint.distance(info.TopRight, info.BottomLeft); float dB = ResultPoint.distance(info.TopLeft, info.TopRight); // Check the sizes float estimatedModuleCount = ((dA + dB) / p1.EstimatedModuleSize) / 2; if (estimatedModuleCount > MAX_MODULE_COUNT_PER_EDGE || estimatedModuleCount < MIN_MODULE_COUNT_PER_EDGE) { continue; } // Calculate the difference of the edge lengths in percent float vABBC = System.Math.Abs(((dA - dB) / System.Math.Min(dA, dB))); if (vABBC >= 0.1f) { continue; } // Calculate the diagonal length by assuming a 90° angle at topleft //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 dCpy = (float)System.Math.Sqrt(dA * dA + dB * dB); // Compare to the real distance in % float vPyC = System.Math.Abs(((dC - dCpy) / System.Math.Min(dC, dCpy))); if (vPyC >= 0.1f) { continue; } // All tests passed! results.Add(test); } // end iterate p3 } // end iterate p2 } // end iterate p1 if (!(results.Count == 0)) { FinderPattern[][] resultArray = new FinderPattern[results.Count][]; for (int i = 0; i < results.Count; i++) { resultArray[i] = (FinderPattern[])results[i]; } return(resultArray); } // Nothing found! throw ReaderException.Instance; }