/// <summary> /// Orders an array of three ResultPoints in an order [A,B,C] such that AB is less than AC and /// BC is less than AC and the angle between BC and BA is less than 180 degrees. /// </summary> /// <param name="patterns">array of three <see cref="ResultPoint" /> to order</param> 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; }
/// <summary> /// calculates the distance between two points /// </summary> /// <param name="pattern1">first pattern</param> /// <param name="pattern2">second pattern</param> /// <returns> /// distance between two points /// </returns> public static float Distance(ResultPoint pattern1, ResultPoint pattern2) { return(MathUtils.Distance(pattern1.X, pattern1.Y, pattern2.X, pattern2.Y)); }
public Result Decode(BinaryBitmap image) { int width = image.Width; int height = image.Height; BitArray row = new BitArray(width); int rowStep = Math.Max(1, height >> 5); int maxLines = 15; // 15 rows spaced 1/32 apart is roughly the middle half of the image int middle = height >> 1; 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. } // Look for a barcode Result result = Reader.DecodeRow(rowNumber, row); if (result == null) { continue; } // We found our barcode if (attempt == 1) { // 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); }