Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to decode from gallery image (null result) #495

Closed
Fralkayg opened this issue Jan 11, 2017 · 9 comments
Closed

Unable to decode from gallery image (null result) #495

Fralkayg opened this issue Jan 11, 2017 · 9 comments

Comments

@Fralkayg
Copy link

Fralkayg commented Jan 11, 2017

I recently created a new project on Xamarin Forms PCL using this library. Im able to scan any code without problem, but another functionality that i need is to decode an image from the dispositive gallery, im retrieving the image in a byte[] (100% sure that the image is correct and obviously is a QR image that im able to scan). This is my code:

       //returns byte[] from image
       var image = await Task.Run(() => mediaController.BrowseGallery());
        if (image != null)
        {
            Bitmap bitmap = BitmapFactory.DecodeByteArray(image, 0, image.Length);
            var bin = new HybridBinarizer(new RGBLuminanceSource(image, bitmap.Width, bitmap.Height));
            var i = new BinaryBitmap(bin);
            var reader = new MultiFormatReader();
            var hints = new Dictionary<DecodeHintType, object>();
            hints.Add(DecodeHintType.PURE_BARCODE, "TRUE");
            hints.Add(DecodeHintType.POSSIBLE_FORMATS, new List<BarcodeFormat>() { BarcodeFormat.QR_CODE });                 
            reader.Hints = hints;
            var result = reader.decode(i, hints);

I have tested in so many ways but still cant figure why this isnt working.
I was following this unit test https://github.com/Redth/ZXing.Net.Mobile/blob/master/Tests/ZXing.Net.Mobile.NUnit/Test.cs

@redwolf2
Copy link

redwolf2 commented Jan 12, 2017

Make sure you receive a RGB888 byte array from the bitmap. you need your byte array like { r, g, b, r, g, b, r, g, b ... }. It may contain an unessessary alpha component like { r, g, b, a, r, g, b, a, r, g, b, a ... } or worse, be 16-Bit and compressed to two bytes (5 bit per color). You can specify the format by using the constructor overload of RGBLuminanceSource with BitmapFormat like RGBLuminanceSource(image, bitmap.Width, bitmap.Height, RGBLuminanceSource.BitmapFormat.<your_format>)

@Fralkayg
Copy link
Author

Fralkayg commented Jan 12, 2017

I did another test using an API (sending the byte array of the image in data.image class)

       Bitmap bmp;
        using (MemoryStream ms = new MemoryStream(data.image))
        {
            bmp = new Bitmap(ms);
        }
        using (bmp)
        {
            IBarcodeReader reader = new BarcodeReader();
            var result = reader.Decode(bmp);
            if (result != null)
            {
                data.imageName = result.Text;
            }
        }

This way im able to decode correctly the image, getting the string that i expect from the QR Code image. Tried to do the same on my app but reader.decode doesnt have a overload that takes a bitmap as parameter.
Tried to apply what you told me, but i dont know how to see the format of my array. ( i need it working on the APP, dont need it on the API)

@redwolf2
Copy link

redwolf2 commented Jan 12, 2017

System.Drawing.Bitmap != Android.Graphics.Bitmap. Most Image classes are platform specific therefore ZXing.Net is not relieant on them.

Have a look at the byte array. If the image is 640x480, the resulting byte array length have to be 640 * 480 * 3 = 921600 bytes

@Fralkayg
Copy link
Author

Im using a 400x400 image, the byte array length is 21.246, not even close to 400x400x(something)

@redwolf2
Copy link

redwolf2 commented Jan 13, 2017

There is your problem. A 400x400 pixel image should have a bytes length of 480000, when passed to RGBLuminanceSource.
My suggestion is, that you get the compressed image bytes in png or jpg format. 400 * 400 / 7 = 22857. Maybe your image is a "binary image". Thus it only consists of black and white pixel. A compression might be applied, shrinking it further down.

You need to do something like this:

Bitmap image = BitmapFactory.DecodeStream(Resources.OpenRawResource(Resource.Raw.test));
byte[] rgbBytes = GetRgbBytes(image);

private static byte[] GetRgbBytes(Bitmap image)
{
	var rgbBytes = new List<byte>();
	for (int y = 0; y < image.Height; y++)
	{
		for (int x = 0; x < image.Width; x++)
		{
			var c = new Color(image.GetPixel(x, y))
			rgbBytes.AddRange(new []{ c.R, c.G, c.B });
		}
	}
	return rgbBytes.ToArray();
}

So in your Code you need to do this:

       //returns byte[] from image
       var image = await Task.Run(() => mediaController.BrowseGallery());
        if (image != null)
        {
            Bitmap bitmap = BitmapFactory.DecodeByteArray(image, 0, image.Length);
            byte[] rgbBytes = GetRgbBytes(bitmap);
            var bin = new HybridBinarizer(new RGBLuminanceSource(rgbBytes, bitmap.Width, bitmap.Height));
            var i = new BinaryBitmap(bin);
            var reader = new MultiFormatReader();
            var hints = new Dictionary<DecodeHintType, object>();
            hints.Add(DecodeHintType.PURE_BARCODE, "TRUE");
            hints.Add(DecodeHintType.POSSIBLE_FORMATS, new List<BarcodeFormat>() { BarcodeFormat.QR_CODE });                 
            reader.Hints = hints;
            var result = reader.decode(i, hints);

Here is the sample code

https://mega.nz/#!65EBEDaC

There might be a faster build in feature to do this in Android though, like Bitmap.GetBuffer().

@mjspk
Copy link

mjspk commented Dec 24, 2018

any code for ios side please

@Redth
Copy link
Owner

Redth commented Mar 13, 2020

Thanks for reporting this issue! Unforunately it took me way too long to respond 😭. Sorry, I apologize! Recently the source code for this project was completely refactored to modernize it. Many PR's were included in this effort, and many bugs were hopefully fixed. Please try out the latest 3.x series of NuGet packages (currently in prerelease). To try and make the project more maintainable in my spare time going forward, I've decided to close all existing issues to start with a clean slate. If you're still experiencing this issue on the newest version, please open a new issue with as much detail as possible. Thank you for your patience and understanding! Happy scanning!

@ognamala
Copy link

ognamala commented Nov 3, 2021

There is your problem. A 400x400 pixel image should have a bytes length of 480000, when passed to RGBLuminanceSource. My suggestion is, that you get the compressed image bytes in png or jpg format. 400 * 400 / 7 = 22857. Maybe your image is a "binary image". Thus it only consists of black and white pixel. A compression might be applied, shrinking it further down.

You need to do something like this:

Bitmap image = BitmapFactory.DecodeStream(Resources.OpenRawResource(Resource.Raw.test));
byte[] rgbBytes = GetRgbBytes(image);

private static byte[] GetRgbBytes(Bitmap image)
{
	var rgbBytes = new List<byte>();
	for (int y = 0; y < image.Height; y++)
	{
		for (int x = 0; x < image.Width; x++)
		{
			var c = new Color(image.GetPixel(x, y))
			rgbBytes.AddRange(new []{ c.R, c.G, c.B });
		}
	}
	return rgbBytes.ToArray();
}

So in your Code you need to do this:

       //returns byte[] from image
       var image = await Task.Run(() => mediaController.BrowseGallery());
        if (image != null)
        {
            Bitmap bitmap = BitmapFactory.DecodeByteArray(image, 0, image.Length);
            byte[] rgbBytes = GetRgbBytes(bitmap);
            var bin = new HybridBinarizer(new RGBLuminanceSource(rgbBytes, bitmap.Width, bitmap.Height));
            var i = new BinaryBitmap(bin);
            var reader = new MultiFormatReader();
            var hints = new Dictionary<DecodeHintType, object>();
            hints.Add(DecodeHintType.PURE_BARCODE, "TRUE");
            hints.Add(DecodeHintType.POSSIBLE_FORMATS, new List<BarcodeFormat>() { BarcodeFormat.QR_CODE });                 
            reader.Hints = hints;
            var result = reader.decode(i, hints);

Here is the sample code

https://mega.nz/#!65EBEDaC

There might be a faster build in feature to do this in Android though, like Bitmap.GetBuffer().

Good evening, the sample code doesn’t seem to be available anymore - could you kindly re-upload? I am currently facing this issue on iOS and really need help on how to address this issue - would really appreciate. Thanks

@nchrisr
Copy link

nchrisr commented Dec 6, 2021

@ognamala Check this out github.com//issues/981 Let me know if that helps

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants