0

I am developing a barcode reader with Xamarin.Forms. And I'm trying to scan the image on Android device.

First I select the image from the gallery with Xamarin.Essentials MediaPicker and from the path of this image I get an RGBLuminance with the Dependency class.

Then I am trying to decode this RGBLuminance with the Decode() method of the ZXing BarcodeReaderGeneric class. However, the result always returns null.

It is my demo project : https://onedrive.live.com/?authkey=%21AFLjjM91wgZkBGU&cid=58BE2C2C3447FFA2&id=58BE2C2C3447FFA2%219829&parId=root&action=locate

Command in the ViewModel class:

        public ICommand PickCommand => new Command(PickImage);
        private async void PickImage()
        {
            var pickResult = await MediaPicker.PickPhotoAsync(new MediaPickerOptions
            {
                Title = "Select a barcode."
            });
            var path = pickResult.FullPath;

            var RGBLuminance = DependencyService.Get<ILuminance>().GetRGBLuminanceSource(path);
            var reader = new BarcodeReaderGeneric();
            var result = reader.Decode(RGBLuminance); // result always null.
        }

Method of Dependency class in Android:

        public RGBLuminanceSource GetRGBLuminanceSource(string imagePath)
        {
            
            if (File.Exists(imagePath))
            {
                Android.Graphics.Bitmap bitmap = BitmapFactory.DecodeFile(imagePath);
                List<byte> rgbBytesList = new List<byte>();
                for (int y = 0; y < bitmap.Height; y++)
                {
                    for (int x = 0; x < bitmap.Width; x++)
                    {
                        var c = new Android.Graphics.Color(bitmap.GetPixel(x, y));
                        rgbBytesList.AddRange(new[] { c.A, c.R, c.G, c.B });
                    }
                }
                byte[] rgbBytes = rgbBytesList.ToArray();
                return new RGBLuminanceSource(rgbBytes, bitmap.Height, bitmap.Width, RGBLuminanceSource.BitmapFormat.RGB32);
            }
            return null;
        }
  • Hi @Serkan Seker, Could you please post the full error log about this problem? It will give us a clue to the problem. If it is convenient for you, could you please post a basic demo to githhub or onedriver so that we can test on our side? – Jessie Zhang -MSFT Apr 14 '21 at 12:56
  • Hi @JessieZhang-MSFT I prepared a demo project. https://onedrive.live.com/?authkey=%21AFLjjM91wgZkBGU&cid=58BE2C2C3447FFA2&id=58BE2C2C3447FFA2%219829&parId=root&action=locate – Serkan Şeker Apr 14 '21 at 13:46

2 Answers2

0

You should change the line

return new RGBLuminanceSource(rgbBytes, bitmap.Height, bitmap.Width, RGBLuminanceSource.BitmapFormat.RGB32);

to

return new RGBLuminanceSource(rgbBytes, bitmap.Width, bitmap.Height, RGBLuminanceSource.BitmapFormat.RGB32);

And to be more accurate with the RGB format you should

  • change RGBLuminanceSource.BitmapFormat.RGB32 to RGBLuminanceSource.BitmapFormat.ARGB32
  • or change rgbBytesList.AddRange(new[] { c.A, c.R, c.G, c.B }); to rgbBytesList.AddRange(new[] { c.R, c.G, c.B, c.A });
Michael
  • 2,361
  • 1
  • 15
  • 15
  • Thank you. Does different BitmapFormat affect the result when scanning barcodes? – Serkan Şeker Apr 14 '21 at 20:52
  • It depends. The luminance source in RGB32 mode uses the first three bytes as R, G and B channel. The fourth byte (alpha channel) is ignored. If you build the array in ARGB order the alpha value is interpreted as red channel, the red channel as green, the green channel as blue and the blue channel would be ignored. That leads to a different grayscale image and in some cases to a different monochrome bit matrix. Some images, perhaps with low contrast or similar, may fail. – Michael Apr 15 '21 at 05:08
  • What is the best BitmapFormat setting to cover all barcode types? Both black-white and color barcodes are available. – Serkan Şeker Apr 15 '21 at 07:16
  • The barcode types don't depend on the bitmap format. You have to select a format that fits your byte array. You can alternatively use the barcode reader class ZXing.Android.BarcodeReader from the android binding package https://www.nuget.org/packages/ZXing.Net.Bindings.Android/. Your code would look like the following in that case: ´´´ if (File.Exists(imagePath)) { Android.Graphics.Bitmap bitmap = BitmapFactory.DecodeFile(imagePath); var reader = new ZXing.Android.BarcodeReader(); var result = reader.Decode(bitmap); } ´´´ – Michael Apr 15 '21 at 18:01
  • What I don't understand is that one image of different sizes with the same content is decoded correctly, while the other returns null. Why is this happening? – Serkan Şeker Apr 15 '21 at 19:37
  • For an answer, I need these two image files. – Michael Apr 16 '21 at 20:04
  • Can you try with pictures below? – Serkan Şeker Apr 17 '21 at 20:01
  • Both images work for me. I tried decoding with the Windows Forms sample application from the ZXing.Net project. I have no idea what's wrong in your case. Did you try the class ZXing.Android.BarcodeReader class from the android binding package? – Michael Apr 19 '21 at 05:43
  • ZXing.Android.BarcodeReader cannot decode a barcode image taken from the camera. Also, how can I use the BarcodeReader class on iOS? I'm developing a Xamarin.Forms project. So I want to add the same feature to the iOS side. – Serkan Şeker Apr 19 '21 at 19:08
  • In that case you should try the ZXing.Net.Mobile project: https://github.com/Redth/ZXing.Net.Mobile – Michael Apr 19 '21 at 19:27
0

Can you try with this pictures?

Picture One Picture Two