Home » Android » android – ZXing convert Bitmap to BinaryBitmap

android – ZXing convert Bitmap to BinaryBitmap

Posted by: admin June 15, 2020 Leave a comment

Questions:

I am using OpenCV and Zxing, and I’d like to add 2d code scanning. I have a few types of images that I could send. Probably the best is Bitmat (the other option is OpenCV Mat).

It looks like you used to be able to convert like this:

Bitmap frame = //this is the frame coming in

LuminanceSource source = new RGBLuminanceSource(frame);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

//then I can use reader.decode(bitmap) to decode the BinaryBitmap

However, RGBLuminaceSource looks like it no longer takes a bitmap as an input. So how else can I convert an input image to BinaryBitmap???

Edit:

Ok so I believe I’ve made some progress, but I’m still having an issue. I think I have the code that converts the Bitmap into the correct format, however I am now getting an arrayIndexOutOfBounds

public void zxing(){
    Bitmap bMap = Bitmap.createBitmap(frame.width(), frame.height(), Bitmap.Config.ARGB_8888);
    Utils.matToBitmap(frame, bMap);
    byte[] array = BitmapToArray(bMap);
    LuminanceSource source = new PlanarYUVLuminanceSource(array, bMap.getWidth(), bMap.getHeight(), 0, 0, bMap.getWidth(), bMap.getHeight(), false);

    BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
    Reader reader = new DataMatrixReader();
    String sResult = "";
    try {
        Result result = reader.decode(bitmap);
        sResult = result.getText();
        Log.i("Result", sResult);
        }
    catch (NotFoundException e) {
            Log.d(TAG, "Code Not Found");
            e.printStackTrace();
    }
}

public byte[] BitmapToArray(Bitmap bmp){
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    bmp.compress(Bitmap.CompressFormat.JPEG, 50, stream);
    byte[] byteArray = stream.toByteArray();
    return byteArray;
}

I get the error

02-14 10:19:27.469: E/AndroidRuntime(29736): java.lang.ArrayIndexOutOfBoundsException: length=33341; index=34560 02-14 10:19:27.469: E/AndroidRuntime(29736):   at 
com.google.zxing.common.HybridBinarizer.calculateBlackPoints(HybridBinarizer.java:199)

I have logged the size of the byte[], and it is the length shown above. I cant figure out why zxing is expecting it to be bigger

How to&Answers:

Ok I got it. As Sean Owen said, PlanarYUVLuminaceSource would only be for the default android camera format, which I guess OpenCV does not use. So in short, here is how you would do it:

//(note, mTwod is the CV Mat that contains my datamatrix code)

Bitmap bMap = Bitmap.createBitmap(mTwod.width(), mTwod.height(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(mTwod, bMap);
int[] intArray = new int[bMap.getWidth()*bMap.getHeight()];  
//copy pixel data from the Bitmap into the 'intArray' array  
bMap.getPixels(intArray, 0, bMap.getWidth(), 0, 0, bMap.getWidth(), bMap.getHeight());  

LuminanceSource source = new RGBLuminanceSource(bMap.getWidth(), bMap.getHeight(),intArray);

BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Reader reader = new DataMatrixReader();     
//....doing the actually reading
Result result = reader.decode(bitmap);

So thats it, not hard at all. Just had to convert the Android Bitmap to an integer array, and its a piece of cake.

Answer:

public static String readQRImage(Bitmap bMap) {
    String contents = null;

    int[] intArray = new int[bMap.getWidth()*bMap.getHeight()];  
    //copy pixel data from the Bitmap into the 'intArray' array  
    bMap.getPixels(intArray, 0, bMap.getWidth(), 0, 0, bMap.getWidth(), bMap.getHeight());  

    LuminanceSource source = new RGBLuminanceSource(bMap.getWidth(), bMap.getHeight(), intArray);
    BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

    Reader reader = new MultiFormatReader();// use this otherwise ChecksumException
    try {
        Result result = reader.decode(bitmap);
        contents = result.getText(); 
        //byte[] rawBytes = result.getRawBytes(); 
        //BarcodeFormat format = result.getBarcodeFormat(); 
        //ResultPoint[] points = result.getResultPoints();
    } catch (NotFoundException e) { e.printStackTrace(); } 
    catch (ChecksumException e) { e.printStackTrace(); }
    catch (FormatException e) { e.printStackTrace(); } 
    return contents;
}

Answer:

Bitmap is an Android class. Android’s default image format from the camera is a planar YUV format. That is why only PlanarYUVLuminanceSource is needed and exists for Android. RGBLuminanceSource would have to be ported.

You are putting completely the wrong kind of data into the class. It is expecting pixels in YUV planar format. You are passing compressed bytes of a JPEG file.