ZXing for ASP.NET MVC to scan barcodes

╄→尐↘猪︶ㄣ 提交于 2019-12-13 10:13:51

问题


I am looking for away to use to use the ZXing library with ASP.NET MVC to scan barcodes, I was able to do this in Xamarin.Forms and now trying to apply the same code to an ASP.NET MVC project. In my Xamarin.Forms I had the following:

            var options = new MobileBarcodeScanningOptions
            {
                TryHarder = true,
                CameraResolutionSelector = HandleCameraResolutionSelectorDelegate,
                PossibleFormats = new List<BarcodeFormat> { BarcodeFormat.PDF_417 },
            };


            BarcodeScanView.Options = options;

            BarcodeScanView.IsVisible = true;
            BarcodeScanView.IsScanning = true;

and I would have an onScan method like so:

public async void OnScanResult(Result result)
{
}

and in my xaml file I had the zxing element like so:

<zxing:ZXingScannerView x:Name="BarcodeScanView" IsVisible="false" HeightRequest="200" OnScanResult="OnScanResult" />

So my question is what would be the equivalent to this in ASP.NET, what would be the equivalent to this zxing element?

Please Help!

UPDATE

I have gone the route of using jQuery for the camera and ZXing.NET to debug the PDF417 Barcode:

Here is my HTML:

<video id="video" width="800" height="800"></video>
<canvas id="canvas" width="800" height="800"></canvas>

And the jQuery for the camera and the code that calls an .NET method to debug the barcode:

var video = document.getElementById('video');

    if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {


        navigator.mediaDevices.getUserMedia({ video: true }).then(function (stream) {
            video.srcObject = stream;
            video.play();
        });
    }

    $("#video").on("playing", function () {

        setInterval(function () { scanBarcode() }, 500);

    });

    function scanBarcode() {

        var video = document.getElementById('video');
        var canvas = document.getElementById('canvas');
        var canvas_context = canvas.getContext('2d');

        canvas_context.drawImage(video, 0, 0, 640, 480);

        var image = document.getElementById("canvas").toDataURL("image/png");

        image = image.replace('data:image/png;base64,', '');

        $.post("Home/OnScan", { imageData: image }, function (data, status) {

            console.log(data);

        });

    }

And here is my .NET method to debug the PDF417 barcode:

public JsonResult OnScan(string imageData)
        {

            BitmapImage bitmapImage = new BitmapImage();
            byte[] byteBuffer = Convert.FromBase64String(imageData);

            Bitmap bmp;
            using (var ms = new MemoryStream(byteBuffer))
            {
                bmp = new Bitmap(ms);
            }

            BarcodeReader reader = new BarcodeReader();

            DecodingOptions options = new DecodingOptions
            {
                TryHarder = true,
                PossibleFormats = new List<BarcodeFormat> { BarcodeFormat.PDF_417 }
            };

            reader.Options = options;

            var result = reader.Decode(bmp);

            return Json(result.Text, JsonRequestBehavior.AllowGet);
        }

Now this still does not work, but I remembered when I first did this in Xamarin.Forms it also did not work until I add the CameraResolutionSelector option:

var options = new MobileBarcodeScanningOptions
            {
                TryHarder = true,
                CameraResolutionSelector = HandleCameraResolutionSelectorDelegate,
                PossibleFormats = new List<BarcodeFormat> { BarcodeFormat.PDF_417 },
            };

Here is the HandleCameraResolutionSelectorDelegate method:

public CameraResolution HandleCameraResolutionSelectorDelegate(List<CameraResolution> availableResolutions)
        {
            //Don't know if this will ever be null or empty
            if (availableResolutions == null || availableResolutions.Count < 1)
                return new CameraResolution() { Width = 800, Height = 600 };

            //Debugging revealed that the last element in the list
            //expresses the highest resolution. This could probably be more thorough.
            return availableResolutions[availableResolutions.Count - 1];
        }

So I am starting to think it the resolution of the camera that is causing my barcode not to scan....on another note when I change BarcodeFormat to QR_CODE and scan a QR code it works, but not with a PDF417 Barcode...what am I doing wrong?


回答1:


As I have have answered already here

I have some instances like the one of this issue, where with an apparently good image reconstruction, zxing can't decode as expected and i'm not competent to figure out why.

Try putting PureBarcode = true will resolve the issue.

DecodingOptions options = new DecodingOptions
{
    TryHarder = true,
    PossibleFormats = new List<BarcodeFormat> { BarcodeFormat.PDF_417 },
    PureBarcode = true,
    AutoRotate = true,
    TryInverted = true,
    CameraResolutionSelector = HandleCameraResolutionSelectorDelegate
};

CameraResolution HandleCameraResolutionSelectorDelegate(List<CameraResolution> availableResolutions)
{
    if (availableResolutions == null || availableResolutions.Count < 1)
        return new CameraResolution () { Width = 800, Height = 600 };   
    return availableResolutions [availableResolutions.Count - 1];
}

Also, There are lot of Decoding options to optimize the Decode which you can use for decoding.

namespace ZXing.Interop.Decoding
{
    /// <summary>
    /// Defines an container for encoder options
    /// </summary>
    [Serializable]
    [ComVisible(true)]
    [Guid("24BE4318-BF09-4542-945D-3A9BF1DF5682")]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    public class DecodingOptions
    {
        internal readonly ZXing.Common.DecodingOptions wrappedDecodingOptions;
        internal readonly BarcodeFormatCollection formatCollection;

        /// <summary>
        /// Gets or sets a flag which cause a deeper look into the bitmap
        /// </summary>
        /// <value>
        ///   <c>true</c> if [try harder]; otherwise, <c>false</c>.
        /// </value>
        public bool TryHarder
        {
            get { return wrappedDecodingOptions.TryHarder; }
            set { wrappedDecodingOptions.TryHarder = value; }
        }

        /// <summary>
        /// Image is a pure monochrome image of a barcode.
        /// </summary>
        /// <value>
        ///   <c>true</c> if monochrome image of a barcode; otherwise, <c>false</c>.
        /// </value>
        public bool PureBarcode
        {
            get { return wrappedDecodingOptions.PureBarcode; }
            set { wrappedDecodingOptions.PureBarcode = value; }
        }

        /// <summary>
        /// Specifies what character encoding to use when decoding, where applicable (type String)
        /// </summary>
        /// <value>
        /// The character set.
        /// </value>
        public string CharacterSet
        {
            get { return wrappedDecodingOptions.CharacterSet; }
            set { wrappedDecodingOptions.CharacterSet = value; }
        }

        /// <summary>
        /// Image is known to be of one of a few possible formats.
        /// Maps to a {@link java.util.List} of {@link BarcodeFormat}s.
        /// </summary>
        /// <value>
        /// The possible formats.
        /// </value>
        public IBarcodeFormatCollection PossibleFormats
        {
            get { return formatCollection; }
        }

        /// <summary>
        /// if Code39 could be detected try to use extended mode for full ASCII character set
        /// </summary>
        public bool UseCode39ExtendedMode
        {
            get { return wrappedDecodingOptions.UseCode39ExtendedMode; }
            set { wrappedDecodingOptions.UseCode39ExtendedMode = value; }
        }

        /// <summary>
        /// Don't fail if a Code39 is detected but can't be decoded in extended mode.
        /// Return the raw Code39 result instead. Maps to <see cref="bool" />.
        /// </summary>
        public bool UseCode39RelaxedExtendedMode
        {
            get { return wrappedDecodingOptions.UseCode39RelaxedExtendedMode; }
            set { wrappedDecodingOptions.UseCode39RelaxedExtendedMode = value; }
        }

        /// <summary>
        /// Assume Code 39 codes employ a check digit. Maps to <see cref="bool" />.
        /// </summary>
        /// <value>
        ///   <c>true</c> if it should assume a Code 39 check digit; otherwise, <c>false</c>.
        /// </value>
        public bool AssumeCode39CheckDigit
        {
            get { return wrappedDecodingOptions.AssumeCode39CheckDigit; }
            set { wrappedDecodingOptions.AssumeCode39CheckDigit = value; }
        }

        /// <summary>
        /// If true, return the start and end digits in a Codabar barcode instead of stripping them. They
        /// are alpha, whereas the rest are numeric. By default, they are stripped, but this causes them
        /// to not be. Doesn't matter what it maps to; use <see cref="bool" />.
        /// </summary>
        public bool ReturnCodabarStartEnd
        {
            get { return wrappedDecodingOptions.ReturnCodabarStartEnd; }
            set { wrappedDecodingOptions.ReturnCodabarStartEnd = value; }
        }

        /// <summary>
        /// Assume the barcode is being processed as a GS1 barcode, and modify behavior as needed.
        /// For example this affects FNC1 handling for Code 128 (aka GS1-128).
        /// </summary>
        /// <value>
        ///   <c>true</c> if it should assume GS1; otherwise, <c>false</c>.
        /// </value>
        public bool AssumeGS1
        {
            get { return wrappedDecodingOptions.AssumeGS1; }
            set { wrappedDecodingOptions.AssumeGS1 = value; }
        }

        /// <summary>
        /// Assume MSI codes employ a check digit. Maps to <see cref="bool" />.
        /// </summary>
        /// <value>
        ///   <c>true</c> if it should assume a MSI check digit; otherwise, <c>false</c>.
        /// </value>
        public bool AssumeMSICheckDigit
        {
            get { return wrappedDecodingOptions.AssumeMSICheckDigit; }
            set { wrappedDecodingOptions.AssumeMSICheckDigit = value; }

        }

        /// <summary>
        /// Allowed lengths of encoded data -- reject anything else. Maps to an int[].
        /// </summary>
        public int[] AllowedLengths
        {
            get { return wrappedDecodingOptions.AllowedLengths; }
            set { wrappedDecodingOptions.AllowedLengths = value; }
        }

        /// <summary>
        /// Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this.
        /// Maps to an int[] of the allowed extension lengths, for example [2], [5], or [2, 5].
        /// If it is optional to have an extension, do not set this hint. If this is set,
        /// and a UPC or EAN barcode is found but an extension is not, then no result will be returned
        /// at all.
        /// </summary>
        public int[] AllowedEANExtensions
        {
            get { return wrappedDecodingOptions.AllowedEANExtensions; }
            set { wrappedDecodingOptions.AllowedEANExtensions = value; }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="DecodingOptions"/> class.
        /// </summary>
        public DecodingOptions()
        {
            wrappedDecodingOptions = new ZXing.Common.DecodingOptions();
            formatCollection = new BarcodeFormatCollection(wrappedDecodingOptions);
        }

        internal DecodingOptions(ZXing.Common.DecodingOptions other)
        {
            wrappedDecodingOptions = other;
            formatCollection = new BarcodeFormatCollection(wrappedDecodingOptions);
        }
    }


来源:https://stackoverflow.com/questions/58917360/zxing-for-asp-net-mvc-to-scan-barcodes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!