private async Task <Result> DetectBarcodeAsync() { var width = (int)PreviewResolution.Width; var height = (int)PreviewResolution.Height; var rotation = PhotoCaptureDevice.SensorRotationInDegrees; LuminanceSource luminanceSource = null; PhotoCaptureDevice.GetPreviewBufferY(_previewBuffer); luminanceSource = new RGBLuminanceSource(_previewBuffer, width, height, RGBLuminanceSource.BitmapFormat.Gray8); var result = _barcodeReader.Decode(luminanceSource); if (result == null) { // ok, one try with rotation by 90 degrees if ((Orientation & PageOrientation.Portrait) == PageOrientation.Portrait) { // if we are in potrait orientation it's better to rotate clockwise // to get it in the right direction luminanceSource = new RGBLuminanceSource(RotateClockwise(_previewBuffer, width, height), height, width, RGBLuminanceSource.BitmapFormat.Gray8); } else { // in landscape we try counter clockwise until we know it better luminanceSource = luminanceSource.rotateCounterClockwise(); } result = _barcodeReader.Decode(luminanceSource); } return(result); }
/// <summary> /// Calculates the final BitMatrix once for all requests. This could be called once from the /// constructor instead, but there are some advantages to doing it lazily, such as making /// profiling easier, and not doing heavy lifting when callers don't expect it. /// </summary> private void binarizeEntireImage() { if (matrix == null) { LuminanceSource source = LuminanceSource; int width = source.Width; int height = source.Height; if (width >= MINIMUM_DIMENSION && height >= MINIMUM_DIMENSION) { byte[] luminances = source.Matrix; int subWidth = width >> BLOCK_SIZE_POWER; if ((width & BLOCK_SIZE_MASK) != 0) { subWidth++; } int subHeight = height >> BLOCK_SIZE_POWER; if ((height & BLOCK_SIZE_MASK) != 0) { subHeight++; } int[][] blackPoints = calculateBlackPoints(luminances, subWidth, subHeight, width, height); var newMatrix = new BitMatrix(width, height); calculateThresholdForBlock(luminances, subWidth, subHeight, width, height, blackPoints, newMatrix); matrix = newMatrix; } else { // If the image is too small, fall back to the global histogram approach. matrix = base.BlackMatrix; } } }
/// <summary> /// Applies simple sharpening to the row data to improve performance of the 1D Readers. /// </summary> /// <param name="y"></param> /// <param name="row"></param> /// <returns></returns> public override BitArray getBlackRow(int y, BitArray row) { LuminanceSource source = LuminanceSource; int width = source.Width; if (row == null || row.Size < width) { row = new BitArray(width); } else { row.clear(); } initArrays(width); byte[] localLuminances = source.getRow(y, luminances); int[] localBuckets = buckets; for (int x = 0; x < width; x++) { localBuckets[(localLuminances[x] & 0xff) >> LUMINANCE_SHIFT]++; } int blackPoint; if (!estimateBlackPoint(localBuckets, out blackPoint)) { return(null); } if (width < 3) { // Special case for very small images for (int x = 0; x < width; x++) { if ((localLuminances[x] & 0xff) < blackPoint) { row[x] = true; } } } else { int left = localLuminances[0] & 0xff; int center = localLuminances[1] & 0xff; for (int x = 1; x < width - 1; x++) { int right = localLuminances[x + 1] & 0xff; // A simple -1 4 -1 box filter with a weight of 2. // ((center << 2) - left - right) >> 1 if (((center * 4) - left - right) / 2 < blackPoint) { row[x] = true; } left = center; center = right; } } return(row); }
protected internal Binarizer(LuminanceSource source) { if (source == null) { throw new ArgumentException("Source must be non-null."); } this.source = source; }
public static string parseWithAllBinarizers(LuminanceSource lum) { var res1 = parse(new GlobalHistogramBinarizer(lum)); // основная бинаризация if (res1 == null) { res1 = parse(new HybridBinarizer(lum)); // вспомогательная бинаризация, если основная не справилась } return(res1); }
public void testCrop() { Assert.IsTrue(SOURCE.CropSupported); LuminanceSource cropped = SOURCE.crop(1, 1, 1, 1); Assert.AreEqual(1, cropped.Height); Assert.AreEqual(1, cropped.Width); // java and .Net differs, not sure, why //var expectedInJava = new byte[] {0x7F}; var expected = new byte[] { 0x95 }; Assert.AreEqual(expected, cropped.getRow(0, null)); }
/// <summary> /// 从二维码图片读取二维码信息 /// </summary> /// <param name="bmap"></param> /// <returns></returns> public static string ReadCode(Bitmap bmap) { if (bmap == null) { throw new Exception("Invalid code pictures."); } LuminanceSource source = null;//[shove] new RGBLuminanceSource(bmap, bmap.Width, bmap.Height); BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); Result result; result = new MultiFormatReader().decode(bitmap); // 如果要捕获异常,用 catch (ReaderException re), re.ToString(); return(result.Text); }
public static string parseLumWithRotations(LuminanceSource lum) { for (var i = 0; i < 4; i++) { Console.WriteLine("lum" + i); var res = parseWithAllBinarizers(lum); if (res != null) { return(res); } if (i == 3) { break; } lum = lum.rotateCounterClockwise(); } return(null); }
// Applies simple sharpening to the row data to improve performance of the 1D Readers. //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public BitArray getBlackRow(int y, BitArray row) throws com.google.zxing.NotFoundException public override BitArray getBlackRow(int y, BitArray row) { LuminanceSource source = LuminanceSource; int width = source.Width; if (row == null || row.Size < width) { row = new BitArray(width); } else { //row.SetAll(false); row.clear(); } initArrays(width); sbyte[] localLuminances = source.getRow(y, luminances); int[] localBuckets = buckets; for (int x = 0; x < width; x++) { int pixel = localLuminances[x] & 0xff; localBuckets[pixel >> LUMINANCE_SHIFT]++; } int blackPoint = estimateBlackPoint(localBuckets); int left = localLuminances[0] & 0xff; int center = localLuminances[1] & 0xff; for (int x = 1; x < width - 1; x++) { int right = localLuminances[x + 1] & 0xff; // A simple -1 4 -1 box filter with a weight of 2. int luminance = ((center << 2) - left - right) >> 1; if (luminance < blackPoint) { //row.Set(x, true); row.set(x); } left = center; center = right; } return(row); }
// Calculates the final BitMatrix once for all requests. This could be called once from the // constructor instead, but there are some advantages to doing it lazily, such as making // profiling easier, and not doing heavy lifting when callers don't expect it. private void binarizeEntireImage() { if (matrix == null) { LuminanceSource source = LuminanceSource; if (source.Width >= MINIMUM_DIMENSION && source.Height >= MINIMUM_DIMENSION) { sbyte[] luminances = source.Matrix; int width = source.Width; int height = source.Height; int subWidth = width >> 3; int subHeight = height >> 3; int[][] blackPoints = calculateBlackPoints(luminances, subWidth, subHeight, width); matrix = new BitMatrix(width, height); calculateThresholdForBlock(luminances, subWidth, subHeight, width, blackPoints, matrix); } else { // If the image is too small, fall back to the global histogram approach. matrix = base.BlackMatrix; } } }
private void Worker() { if (hints == null) { hints = new Hashtable(); hints.Add(com.google.zxing.DecodeHintType.POSSIBLE_FORMATS, this.Options.GetFormats()); hints.Add(com.google.zxing.DecodeHintType.NEED_RESULT_POINT_CALLBACK, new ResultCallBack(this)); } if (_multiFormatReader == null) { //_multiFormatReader = new com.google.zxing.oned.MultiFormatOneDReader(hints); _multiFormatReader = new com.google.zxing.MultiFormatReader(); _multiFormatReader.Hints = hints; //_multiFormatReader = new MultiFormatReader { // Hints = new Hashtable { // { DecodeHintType.POSSIBLE_FORMATS, new ArrayList { // BarcodeFormat.UPC_A, BarcodeFormat.UPC_E , BarcodeFormat.CODE_128, // BarcodeFormat.CODE_39, BarcodeFormat.EAN_13, BarcodeFormat.EAN_8 // } } // } // }; } using (var ap = new NSAutoreleasePool()) { // Capturing screen image using (var screenImage = CGImage.ScreenImage.WithImageInRect(picFrame)) //.WithImageInRect(picFrame)) { using (var _theScreenImage = UIImage.FromImage(screenImage)) using (var srcbitmap = new Bitmap(_theScreenImage)) { LuminanceSource source = null; BinaryBitmap bitmap = null; try { //Console.WriteLine(screenImage.Width.ToString() + " x " + screenImage.Height.ToString()); //var cropY = (int)((screenImage.Height * 0.4) / 2); source = new RGBLuminanceSource(srcbitmap, screenImage.Width, screenImage.Height); //.crop(0, cropY, 0, screenImage.Height - cropY - cropY); //Console.WriteLine(source.Width + " x " + source.Height); bitmap = new BinaryBitmap(new HybridBinarizer(source)); try { var result = _multiFormatReader.decodeWithState(bitmap); // //var result = _multiFormatReader.decodeWithState (bitmap); //srcbitmap.Dispose(); if (result.Text != null) { //BeepOrVibrate(); _parentViewController.BarCodeScanned(result); } } catch (ReaderException) { } /* * com.google.zxing.common.BitArray row = new com.google.zxing.common.BitArray(screenImage.Width); * * int middle = screenImage.Height >> 1; * int rowStep = System.Math.Max(1, screenImage.Height >> (4)); * * for (int x = 0; x < 9; 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 >= screenImage.Height) * { * // Oops, if we run off the top or bottom, stop * break; * } * * // Estimate black point for this row and load it: * try * { * row = bitmap.getBlackRow(rowNumber, row); * * * var resultb = _multiFormatReader.decodeRow(rowNumber, row, hints); * if(resultb.Text!=null) * { * Console.WriteLine("SCANNED"); * BeepOrVibrate(); * _parentViewController.BarCodeScanned(resultb); * * * break; * } * else { * continue; * } * * } * catch (ReaderException re) * { * continue; * } * * } */ // var result = _barcodeReader.decodeWithState(bitmap); // // if(result.Text!=null) // { // _multiFormatOneDReader = null; // BeepOrVibrate(); // _parentViewController.BarCodeScanned(result); // } } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { if (bitmap != null) { bitmap = null; } if (source != null) { source = null; } // if(srcbitmap!=null) // srcbitmap = null; //if (_theScreenImage != null) // _theScreenImage = null; } } } } GC.Collect(); //Console.WriteLine("Done."); }
public GlobalHistogramBinarizer(LuminanceSource source) : base(source) { luminances = EMPTY; buckets = new int[LUMINANCE_BUCKETS]; }
public GlobalHistogramBinarizer(LuminanceSource source):base(source) { }
public override Binarizer createBinarizer(LuminanceSource source) { return(new HybridBinarizer(source)); }
static Binarizer CreateBinarizer(LuminanceSource luminanceSource) { return(new HybridBinarizer(luminanceSource)); }
/// <summary> /// HybridBinarizer() /// </summary> /// <param name="source"></param> public HybridBinarizer(LuminanceSource source) : base(source) { }
/// <summary> /// Returns a new object with rotated image data by 45 degrees counterclockwise. /// Only callable if {@link #isRotateSupported()} is true. /// </summary> /// <returns>A rotated version of this object.</returns> public BinaryBitmap rotateCounterClockwise45() { LuminanceSource newSource = binarizer.LuminanceSource.rotateCounterClockwise45(); return(new BinaryBitmap(binarizer.createBinarizer(newSource))); }
/// <summary> /// Initializes a new instance of the <see cref="GlobalHistogramBinarizer"/> class. /// </summary> /// <param name="source">The source.</param> public GlobalHistogramBinarizer(LuminanceSource source) : base(source) { luminances = EMPTY; buckets = new int[LUMINANCE_BUCKETS]; }
/// <summary> /// Initializes a new instance of the <see cref="InvertedLuminanceSource"/> class. /// </summary> /// <param name="delegate">The @delegate.</param> public InvertedLuminanceSource(LuminanceSource @delegate) : base(@delegate.Width, @delegate.Height) { this.@delegate = @delegate; }
public override Binarizer createBinarizer(LuminanceSource source) { return new GlobalHistogramBinarizer(source); }
private void Worker() { //iphone 4 : 960 x 640 //iphone 3 : 320 x 480 if (DeviceHardware.Version == DeviceHardware.HardwareVersion.iPhone4) { picFrame = new RectangleF(0, 146 * 2, 320 * 2, 157 * 2); } if (hints == null) { var list = new ArrayList(); list.Add(com.google.zxing.BarcodeFormat.EAN_8); list.Add(com.google.zxing.BarcodeFormat.EAN_13); hints = new Hashtable(); hints.Add(com.google.zxing.DecodeHintType.POSSIBLE_FORMATS, list); hints.Add(com.google.zxing.DecodeHintType.NEED_RESULT_POINT_CALLBACK, new ResultCallBack(this)); } if (_multiFormatOneDReader == null) { _multiFormatOneDReader = new com.google.zxing.oned.MultiFormatOneDReader(hints); } // Capturing screen image using (var screenImage = CGImage.ScreenImage.WithImageInRect(picFrame)) { _theScreenImage = UIImage.FromImage(screenImage); Bitmap srcbitmap = new System.Drawing.Bitmap(_theScreenImage); LuminanceSource source = null; BinaryBitmap bitmap = null; try { source = new RGBLuminanceSource(srcbitmap, screenImage.Width, screenImage.Height); bitmap = new BinaryBitmap(new HybridBinarizer(source)); com.google.zxing.common.BitArray row = new com.google.zxing.common.BitArray(screenImage.Width); int middle = screenImage.Height >> 1; int rowStep = System.Math.Max(1, screenImage.Height >> (4)); for (int x = 0; x < 9; 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 >= screenImage.Height) { // Oops, if we run off the top or bottom, stop break; } // Estimate black point for this row and load it: try { row = bitmap.getBlackRow(rowNumber, row); var resultb = _multiFormatOneDReader.decodeRow(rowNumber, row, hints); if (resultb.Text != null) { BeepOrVibrate(); _parentViewController.BarCodeScanned(resultb); break; } else { continue; } } catch (ReaderException re) { continue; } } // var result = _barcodeReader.decodeWithState(bitmap); // // if(result.Text!=null) // { // _multiFormatOneDReader = null; // BeepOrVibrate(); // _parentViewController.BarCodeScanned(result); // } } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { if (bitmap != null) { bitmap = null; } if (source != null) { source = null; } if (srcbitmap != null) { srcbitmap = null; } } } }
/** * Writes out a single PNG which is three times the width of the input image, containing from left * to right: the original image, the row sampling monochrome version, and the 2D sampling * monochrome version. */ private static void dumpBlackPoint(Uri uri, Bitmap image, BinaryBitmap bitmap, LuminanceSource luminanceSource) { // TODO: Update to compare different Binarizer implementations. String inputName = uri.LocalPath; if (inputName.Contains(".mono.png")) { return; } // Use the current working directory for URLs String resultName = inputName; int pos; if ("http".Equals(uri.Scheme)) { pos = resultName.LastIndexOf('/'); if (pos > 0) { resultName = '.' + resultName.Substring(pos); } } pos = resultName.LastIndexOf('.'); if (pos > 0) { resultName = resultName.Substring(0, pos); } resultName += ".mono.png"; int width = bitmap.Width; int height = bitmap.Height; int stride = width * 4; var result = new Bitmap(stride, height, PixelFormat.Format32bppArgb); var offset = 0; // The original image for (int indexH = 0; indexH < height; indexH++) { for (int indexW = 0; indexW < width; indexW++) { result.SetPixel(indexW, indexH, image.GetPixel(indexW, indexH)); } } // Row sampling BitArray row = new BitArray(width); offset += width; for (int y = 0; y < height; y++) { row = bitmap.getBlackRow(y, row); if (row == null) { // If fetching the row failed, draw a red line and keep going. for (int x = 0; x < width; x++) { result.SetPixel(offset + x, y, Color.Red); } continue; } for (int x = 0; x < width; x++) { result.SetPixel(offset + x, y, row[x] ? Color.Black : Color.White); } } // 2D sampling offset += width; BitMatrix matrix = bitmap.BlackMatrix; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { result.SetPixel(offset + x, y, matrix[x, y] ? Color.Black : Color.White); } } offset += width; var luminanceMatrix = luminanceSource.Matrix; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { result.SetPixel(offset + x, y, Color.FromArgb(luminanceMatrix[y * width + x], luminanceMatrix[y * width + x], luminanceMatrix[y * width + x])); } } result.Save(resultName, ImageFormat.Png); }
/// <summary> Creates a new object with the same type as this Binarizer implementation, but with pristine /// state. This is needed because Binarizer implementations may be stateful, e.g. keeping a cache /// of 1 bit data. See Effective Java for why we can't use Java's clone() method. /// /// </summary> /// <param name="source">The LuminanceSource this Binarizer will operate on. /// </param> /// <returns> A new concrete Binarizer implementation object. /// </returns> public abstract Binarizer createBinarizer(LuminanceSource source);
/// <summary> /// createBinarizer() /// </summary> /// <param name="source"></param> /// <returns></returns> public override Binarizer createBinarizer(LuminanceSource source) { return new HybridBinarizer(source); }
public HybridBinarizer(LuminanceSource source) : base(source) { }
public override Binarizer createBinarizer(LuminanceSource source) { return(new GlobalHistogramBinarizer(source)); }
public GlobalHistogramBinarizer(LuminanceSource source) : base(source) { }
protected GlobalHistogramBinarizer(LuminanceSource source) : base(source) { }