ShujatAli
ShujatAli

Reputation: 1376

ZBar Android scan local QR or bar code image

I am trying to scan a local image through ZBar, but as ZBar don't give any documentation for Android but only give detailed documentation for iPhone I had customized camera test activity too much. But I didn't get any success.

In ZBar cameratest activity

PreviewCallback previewCb = new PreviewCallback() {
    public void onPreviewFrame(byte[] data, Camera camera) {
        Camera.Parameters parameters = camera.getParameters();
        Size size = parameters.getPreviewSize();

        Image barcode = new Image(size.width, size.height, "Y800");
        barcode.setData(data);

        int result = scanner.scanImage(barcode);

        if (result != 0) {
            previewing = false;
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();

            SymbolSet syms = scanner.getResults();
            for (Symbol sym : syms) {
                scanText.setText("barcode result " + sym.getData());
                barcodeScanned = true;
            }
        }
    }
};

I want to customize this code so that it uses a local image from the gallery and gives me the result. How do I customize this code for giving a local image from the gallery and scan that image?

Upvotes: 2

Views: 10759

Answers (4)

frederickha
frederickha

Reputation: 368

Idea from HOWTO: Scan images using the API:

#include <iostream>
#include <Magick++.h>
#include <zbar.h>

using namespace std;
using namespace zbar;

int main (int argc, char **argv)
{
    if(argc < 2)
        return(1);

    // Create a reader
    ImageScanner scanner;

    // Configure the reader
    scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);

    // Obtain image data
    Magick::Image magick(argv[1]);  // Read an image file
    int width = magick.columns();   // Extract dimensions
    int height = magick.rows();
    Magick::Blob blob;              // Extract the raw data
    magick.modifyImage();
    magick.write(&blob, "GRAY", 8);
    const void *raw = blob.data();

    // Wrap image data
    Image image(width, height, "Y800", raw, width * height);

    // Scan the image for barcodes
    int n = scanner.scan(image);

    // Extract results
    for (Image::SymbolIterator symbol = image.symbol_begin();
        symbol != image.symbol_end();
        ++symbol) {

        // Do something useful with results
        cout << "decoded " << symbol->get_type_name()
             << " symbol \"" << symbol->get_data() << '"' << endl;
    }

    // Clean up
    image.set_data(NULL, 0);

    return(0);
}

Follow the above code and change it so it is relevant in your language programming.

Upvotes: -2

frederickha
frederickha

Reputation: 368

Try this out:

Bitmap barcodeBmp = BitmapFactory.decodeResource(getResources(),
                                                 R.drawable.barcode);
int width = barcodeBmp.getWidth();
int height = barcodeBmp.getHeight();
int pixels = new int;
barcodeBmp.getPixels(pixels, 0, width, 0, 0, width, height);
Image barcode = new Image(width, height, "RGB4");
barcode.setData(pixels);
int result = scanner.scanImage(barcode.convert("Y800"));

Or using the API, refer to HOWTO: Scan images using the API.

Upvotes: 4

frederickha
frederickha

Reputation: 368

I don't know clearly for Android, but on iOS do as:

//Action when user tap on button to call ZBarReaderController

- (IBAction)brownQRImageFromAlbum:(id)sender {
    ZBarReaderController *reader = [ZBarReaderController new];
    reader.readerDelegate = self;
    reader.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; // Set ZbarReaderController point to the local album
    ZBarImageScanner *scanner = reader.scanner;
    [scanner setSymbology: ZBAR_QRCODE
                   config: ZBAR_CFG_ENABLE
                       to: 1];
    [self presentModalViewController: reader animated: YES];

}


- (void) imagePickerController: (UIImagePickerController *) picker
                  didFinishPickingMediaWithInfo: (NSDictionary *) info {

    UIImage *imageCurrent = (UIImage*)[info objectForKey:UIImagePickerControllerOriginalImage];
    self.imageViewQR.image = imageCurrent;
    imageCurrent = nil;

    // ADD: get the decode results
    id<NSFastEnumeration> results =
    [info objectForKey: ZBarReaderControllerResults];
    ZBarSymbol *symbol = nil;
    for (symbol in results)
        break;

    NSLog(@"Content: %@", symbol.data);

    [picker dismissModalViewControllerAnimated: NO];
}

Reference for more details: http://zbar.sourceforge.net/iphone/sdkdoc/optimizing.html

Upvotes: 1

Pavel
Pavel

Reputation: 323

Java port of Zbar's scanner accepts only Y800 and GRAY pixels format (https://github.com/ZBar/ZBar/blob/master/java/net/sourceforge/zbar/ImageScanner.java) which is ok for raw bytes captured from the camera preview. But images from the Androis's Gallery are JPEG comressed usually and their pixels are not in Y800, so you can make scanner work by converting image's pixels to Y800 format. See this official support forum's thread for sample code. To calculate pixels array length just use imageWidth*imageHeight formula.

@shujatAli your example image palette's format is grayscale, convertation it to RGB made your code snippet to work for me. You can change pallete's format using some image manipulation program. I used GIMP.

Upvotes: 1

Related Questions