/// <summary> /// Decodes the multiple. /// </summary> /// <param name="image">The image.</param> /// <param name="hints">The hints.</param> /// <returns></returns> public Result[] decodeMultiple(BinaryBitmap image, IDictionary<DecodeHintType, object> hints) { var results = new List<Result>(); var detectorResults = new MultiDetector(image.BlackMatrix).detectMulti(hints); foreach (DetectorResult detectorResult in detectorResults) { var decoderResult = getDecoder().decode(detectorResult.Bits, hints); if (decoderResult == null) continue; var points = detectorResult.Points; var result = new Result(decoderResult.Text, decoderResult.RawBytes, points, BarcodeFormat.QR_CODE); var byteSegments = decoderResult.ByteSegments; if (byteSegments != null) { result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments); } var ecLevel = decoderResult.ECLevel; if (ecLevel != null) { result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); } if (decoderResult.StructuredAppend) { result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE, decoderResult.StructuredAppendSequenceNumber); result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_PARITY, decoderResult.StructuredAppendParity); } results.Add(result); } results = ProcessStructuredAppend(results); return results.Count == 0 ? EMPTY_RESULT_ARRAY : results.ToArray(); }
public Result decode(BinaryBitmap image, System.Collections.Generic.Dictionary <Object,Object> hints) { DecoderResult decoderResult; ResultPoint[] points; if (hints != null && hints.ContainsKey(DecodeHintType.PURE_BARCODE)) { BitMatrix bits = extractPureBits(image.BlackMatrix); decoderResult = decoder.decode(bits); points = NO_POINTS; } else { DetectorResult detectorResult = new Detector(image.BlackMatrix).detect(); decoderResult = decoder.decode(detectorResult.Bits); points = detectorResult.Points; } Result result = new Result(decoderResult.Text, decoderResult.RawBytes, points, BarcodeFormat.DATAMATRIX); if (decoderResult.ByteSegments != null) { result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, decoderResult.ByteSegments); } if (decoderResult.ECLevel != null) { result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, decoderResult.ECLevel.ToString()); } return result; }
/// <summary> /// Decodes the multiple. /// </summary> /// <param name="image">The image.</param> /// <param name="hints">The hints.</param> /// <returns></returns> public Result[] decodeMultiple(BinaryBitmap image, IDictionary<DecodeHintType, object> hints) { var results = new List<Result>(); var detectorResults = new MultiDetector(image.BlackMatrix).detectMulti(hints); foreach (DetectorResult detectorResult in detectorResults) { var decoderResult = getDecoder().decode(detectorResult.Bits, hints); if (decoderResult == null) continue; var points = detectorResult.Points; // If the code was mirrored: swap the bottom-left and the top-right points. var data = decoderResult.Other as QRCodeDecoderMetaData; if (data != null) { data.applyMirroredCorrection(points); } var result = new Result(decoderResult.Text, decoderResult.RawBytes, points, BarcodeFormat.QR_CODE); var byteSegments = decoderResult.ByteSegments; if (byteSegments != null) { result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments); } var ecLevel = decoderResult.ECLevel; if (ecLevel != null) { result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); } if (decoderResult.StructuredAppend) { result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE, decoderResult.StructuredAppendSequenceNumber); result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_PARITY, decoderResult.StructuredAppendParity); } results.Add(result); } if (results.Count == 0) { return null; } results = ProcessStructuredAppend(results); return results.ToArray(); }
public Result[] decodeMultiple(BinaryBitmap image, Dictionary<DecodeHintType, Object> hints) { var results = new List<Result>(10); DetectorResult[] detectorResult = new MultiDetector(image.BlackMatrix).detectMulti(hints); foreach (DetectorResult t in detectorResult) { try { DecoderResult decoderResult = Decoder.decode(t.Bits); ResultPoint[] points = t.Points; var result = new Result(decoderResult.Text, decoderResult.RawBytes, points, BarcodeFormat.QR_CODE); if (decoderResult.ByteSegments != null) { result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, decoderResult.ByteSegments); } if (decoderResult.ECLevel != null) { result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, decoderResult.ECLevel.ToString()); } results.Add(result); } catch (ReaderException) { // ignore and continue } } if ((results.Count == 0)) { return EMPTY_RESULT_ARRAY; } var resultArray = new Result[results.Count]; for (int i = 0; i < results.Count; i++) { resultArray[i] = (Result) results[i]; } return resultArray; }
public Result decode(MonochromeBitmapSource image, Hashtable hints) { try{ DecoderResult decoderResult; ResultPoint[] points; if (hints != null && hints.ContainsKey(DecodeHintType.PURE_BARCODE)) { BitMatrix bits = extractPureBits(image); decoderResult = decoder.decode(bits); points = NO_POINTS; } else { DetectorResult detectorResult = new Detector(image).detect(hints); decoderResult = decoder.decode(detectorResult.getBits()); points = detectorResult.getPoints(); } Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.QR_CODE); if (decoderResult.getByteSegments() != null) { result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, decoderResult.getByteSegments()); } return result; }catch(Exception e){ throw new ReaderException(e.Message); } }
/// <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. /// </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> public Result decode(BinaryBitmap image, IDictionary<DecodeHintType, object> hints) { DecoderResult decoderResult; ResultPoint[] points; if (image == null || image.BlackMatrix == null) { // something is wrong with the image return null; } if (hints != null && hints.ContainsKey(DecodeHintType.PURE_BARCODE)) { BitMatrix bits = extractPureBits(image.BlackMatrix); if (bits == null) return null; decoderResult = decoder.decode(bits, hints); points = NO_POINTS; } else { DetectorResult detectorResult = new Detector(image.BlackMatrix).detect(hints); if (detectorResult == null) return null; decoderResult = decoder.decode(detectorResult.Bits, hints); points = detectorResult.Points; } if (decoderResult == null) return null; Result result = new Result(decoderResult.Text, decoderResult.RawBytes, points, BarcodeFormat.QR_CODE); IList<byte[]> byteSegments = decoderResult.ByteSegments; if (byteSegments != null) { result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments); } var ecLevel = decoderResult.ECLevel; if (ecLevel != null) { result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); } return result; }
/// <summary> /// <p>Like decodeRow(int, BitArray, java.util.Map), but /// allows caller to inform method about where the UPC/EAN start pattern is /// found. This allows this to be computed once and reused across many implementations.</p> /// </summary> /// <param name="rowNumber">row index into the image</param> /// <param name="row">encoding of the row of the barcode image</param> /// <param name="startGuardRange">start/end column where the opening start pattern was found</param> /// <param name="hints">optional hints that influence decoding</param> /// <returns><see cref="Result"/> encapsulating the result of decoding a barcode in the row</returns> virtual public Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange, IDictionary<DecodeHintType, object> hints) { var resultPointCallback = hints == null || !hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK) ? null : (ResultPointCallback)hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; if (resultPointCallback != null) { resultPointCallback(new ResultPoint( (startGuardRange[0] + startGuardRange[1]) / 2.0f, rowNumber )); } var result = decodeRowStringBuffer; result.Length = 0; var endStart = decodeMiddle(row, startGuardRange, result); if (endStart < 0) return null; if (resultPointCallback != null) { resultPointCallback(new ResultPoint( endStart, rowNumber )); } var endRange = decodeEnd(row, endStart); if (endRange == null) return null; if (resultPointCallback != null) { resultPointCallback(new ResultPoint( (endRange[0] + endRange[1]) / 2.0f, rowNumber )); } // Make sure there is a quiet zone at least as big as the end pattern after the barcode. The // spec might want more whitespace, but in practice this is the maximum we can count on. var end = endRange[1]; var quietEnd = end + (end - endRange[0]); if (quietEnd >= row.Size || !row.isRange(end, quietEnd, false)) { return null; } var resultString = result.ToString(); // UPC/EAN should never be less than 8 chars anyway if (resultString.Length < 8) { return null; } if (!checkChecksum(resultString)) { return null; } var left = (startGuardRange[1] + startGuardRange[0]) / 2.0f; var right = (endRange[1] + endRange[0]) / 2.0f; var format = BarcodeFormat; var decodeResult = new Result(resultString, null, // no natural byte representation for these barcodes new ResultPoint[] { new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber) }, format); var extensionResult = extensionReader.decodeRow(rowNumber, row, endRange[1]); if (extensionResult != null) { decodeResult.putMetadata(ResultMetadataType.UPC_EAN_EXTENSION, extensionResult.Text); decodeResult.putAllMetadata(extensionResult.ResultMetadata); decodeResult.addResultPoints(extensionResult.ResultPoints); int extensionLength = extensionResult.Text.Length; int[] allowedExtensions = hints != null && hints.ContainsKey(DecodeHintType.ALLOWED_EAN_EXTENSIONS) ? (int[]) hints[DecodeHintType.ALLOWED_EAN_EXTENSIONS] : null; if (allowedExtensions != null) { bool valid = false; foreach (int length in allowedExtensions) { if (extensionLength == length) { valid = true; break; } } if (!valid) { return null; } } } if (format == BarcodeFormat.EAN_13 || format == BarcodeFormat.UPC_A) { String countryID = eanManSupport.lookupCountryIdentifier(resultString); if (countryID != null) { decodeResult.putMetadata(ResultMetadataType.POSSIBLE_COUNTRY, countryID); } } return decodeResult; }
/// <summary> /// Decode the specified image, with the hints and optionally multiple barcodes. /// 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. /// </summary> /// <param name="image">Image.</param> /// <param name="hints">Hints.</param> /// <param name="multiple">If set to <c>true</c> multiple.</param> private static Result[] Decode(BinaryBitmap image, IDictionary<DecodeHintType, object> hints, bool multiple) { List<Result> results = new List<Result>(); PDF417DetectorResult detectorResult = Detector.Detect(image, hints, multiple); foreach (ResultPoint[] points in detectorResult.Points) { DecoderResult decoderResult = PDF417ScanningDecoder.Decode(detectorResult.Bits, points[4], points[5], points[6], points[7], GetMinCodewordWidth(points), GetMaxCodewordWidth(points)); if (decoderResult == null) { // See comments re: Exceptions above // continue; throw ReaderException.Instance; } System.Diagnostics.Debug.WriteLine("Result " + points.ToString() + " > " + decoderResult.Text + " " + decoderResult.RawBytes); Result result = new Result(decoderResult.Text, decoderResult.RawBytes, points, BarcodeFormat.PDF_417); result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, decoderResult.ECLevel); PDF417ResultMetadata pdf417ResultMetadata = (PDF417ResultMetadata)decoderResult.Other; if (pdf417ResultMetadata != null) { result.putMetadata(ResultMetadataType.PDF417_EXTRA_METADATA, pdf417ResultMetadata); } results.Add(result); } return results.ToArray(); }
/// <summary> /// Decode the specified image, with the hints and optionally multiple barcodes. /// 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. /// </summary> /// <param name="image">Image.</param> /// <param name="hints">Hints.</param> /// <param name="multiple">If set to <c>true</c> multiple.</param> private static Result[] decode(BinaryBitmap image, IDictionary<DecodeHintType, object> hints, bool multiple) { var results = new List<Result>(); var detectorResult = Detector.detect(image, hints, multiple); if (detectorResult != null) { foreach (var points in detectorResult.Points) { var decoderResult = PDF417ScanningDecoder.decode(detectorResult.Bits, points[4], points[5], points[6], points[7], getMinCodewordWidth(points), getMaxCodewordWidth(points)); if (decoderResult == null) { continue; } var result = new Result(decoderResult.Text, decoderResult.RawBytes, points, BarcodeFormat.PDF_417); result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, decoderResult.ECLevel); var pdf417ResultMetadata = (PDF417ResultMetadata) decoderResult.Other; if (pdf417ResultMetadata != null) { result.putMetadata(ResultMetadataType.PDF417_EXTRA_METADATA, pdf417ResultMetadata); } results.Add(result); } } return results.ToArray(); }
/// <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. /// </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> public Result decode(BinaryBitmap image, IDictionary<DecodeHintType, object> hints) { DecoderResult decoderResult; ResultPoint[] points; if (image == null || image.BlackMatrix == null) { // something is wrong with the image return null; } if (hints != null && hints.ContainsKey(DecodeHintType.PURE_BARCODE)) { var bits = extractPureBits(image.BlackMatrix); if (bits == null) return null; decoderResult = decoder.decode(bits, hints); points = NO_POINTS; } else { var detectorResult = new Detector(image.BlackMatrix).detect(hints); if (detectorResult == null) return null; decoderResult = decoder.decode(detectorResult.Bits, hints); points = detectorResult.Points; } if (decoderResult == null) return null; // If the code was mirrored: swap the bottom-left and the top-right points. var data = decoderResult.Other as QRCodeDecoderMetaData; if (data != null) { data.applyMirroredCorrection(points); } var result = new Result(decoderResult.Text, decoderResult.RawBytes, points, BarcodeFormat.QR_CODE); var byteSegments = decoderResult.ByteSegments; if (byteSegments != null) { result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments); } var ecLevel = decoderResult.ECLevel; if (ecLevel != null) { result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); } if (decoderResult.StructuredAppend) { result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE, decoderResult.StructuredAppendSequenceNumber); result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_PARITY, decoderResult.StructuredAppendParity); } return result; }
/// <summary> /// <p>Like decodeRow(int, BitArray, java.util.Map), but /// allows caller to inform method about where the UPC/EAN start pattern is /// found. This allows this to be computed once and reused across many implementations.</p> /// </summary> virtual public Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange, IDictionary<DecodeHintType, object> hints) { ResultPointCallback resultPointCallback = hints == null || !hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK) ? null : (ResultPointCallback)hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; if (resultPointCallback != null) { resultPointCallback(new ResultPoint( (startGuardRange[0] + startGuardRange[1]) / 2.0f, rowNumber )); } StringBuilder result = decodeRowStringBuffer; result.Length = 0; int endStart = decodeMiddle(row, startGuardRange, result); if (endStart < 0) return null; if (resultPointCallback != null) { resultPointCallback(new ResultPoint( endStart, rowNumber )); } int[] endRange = decodeEnd(row, endStart); if (endRange == null) return null; if (resultPointCallback != null) { resultPointCallback(new ResultPoint( (endRange[0] + endRange[1]) / 2.0f, rowNumber )); } // Make sure there is a quiet zone at least as big as the end pattern after the barcode. The // spec might want more whitespace, but in practice this is the maximum we can count on. int end = endRange[1]; int quietEnd = end + (end - endRange[0]); if (quietEnd >= row.Size || !row.isRange(end, quietEnd, false)) { return null; } String resultString = result.ToString(); if (!checkChecksum(resultString)) { return null; } float left = (startGuardRange[1] + startGuardRange[0]) / 2.0f; float right = (endRange[1] + endRange[0]) / 2.0f; BarcodeFormat format = BarcodeFormat; Result decodeResult = new Result(resultString, null, // no natural byte representation for these barcodes new ResultPoint[] { new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber) }, format); Result extensionResult = extensionReader.decodeRow(rowNumber, row, endRange[1]); if (extensionResult != null) { decodeResult.putMetadata(ResultMetadataType.UPC_EAN_EXTENSION, extensionResult.Text); decodeResult.putAllMetadata(extensionResult.ResultMetadata); decodeResult.addResultPoints(extensionResult.ResultPoints); } if (format == BarcodeFormat.EAN_13 || format == BarcodeFormat.UPC_A) { String countryID = eanManSupport.lookupCountryIdentifier(resultString); if (countryID != null) { decodeResult.putMetadata(ResultMetadataType.POSSIBLE_COUNTRY, countryID); } } return decodeResult; }
private List<Result> ProcessStructuredAppend(List<Result> results) { bool hasSA = false; // first, check, if there is at least on SA result in the list foreach (var result in results) { if (result.ResultMetadata.ContainsKey(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE)) { hasSA = true; break; } } if (!hasSA) { return results; } // it is, second, split the lists and built a new result list var newResults = new List<Result>(); var saResults = new List<Result>(); foreach (var result in results) { newResults.Add(result); if (result.ResultMetadata.ContainsKey(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE)) { saResults.Add(result); } } // sort and concatenate the SA list items saResults.Sort(SaSequenceSort); var concatedText = String.Empty; var rawBytesLen = 0; int byteSegmentLength = 0; foreach (var saResult in saResults) { concatedText += saResult.Text; rawBytesLen += saResult.RawBytes.Length; if (saResult.ResultMetadata.ContainsKey(ResultMetadataType.BYTE_SEGMENTS)) { foreach (var segment in (IEnumerable<byte[]>) saResult.ResultMetadata[ResultMetadataType.BYTE_SEGMENTS]) { byteSegmentLength += segment.Length; } } } var newRawBytes = new byte[rawBytesLen]; byte[] newByteSegment = new byte[byteSegmentLength]; int newRawBytesIndex = 0; int byteSegmentIndex = 0; foreach (var saResult in saResults) { Array.Copy(saResult.RawBytes, 0, newRawBytes, newRawBytesIndex, saResult.RawBytes.Length); newRawBytesIndex += saResult.RawBytes.Length; if (saResult.ResultMetadata.ContainsKey(ResultMetadataType.BYTE_SEGMENTS)) { foreach (var segment in (IEnumerable<byte[]>) saResult.ResultMetadata[ResultMetadataType.BYTE_SEGMENTS]) { Array.Copy(segment, 0, newByteSegment, byteSegmentIndex, segment.Length); byteSegmentIndex += segment.Length; } } } Result newResult = new Result(concatedText, newRawBytes, NO_POINTS, BarcodeFormat.QR_CODE); if (byteSegmentLength > 0) { var byteSegmentList = new List<byte[]>(); byteSegmentList.Add(newByteSegment); newResult.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegmentList); } newResults.Add(newResult); return newResults; }