journeyapps / zxing-android-embedded

Barcode scanner library for Android, based on the ZXing decoder
https://journeyapps.com/
Apache License 2.0
5.73k stars 1.27k forks source link

How to capture an image? #183

Closed Bajranghudda1 closed 5 years ago

Bajranghudda1 commented 8 years ago

In my app i'm using scanner app, and on the scanning screen i want to take a picture on a button click. So what class or how i can capture the image using the same library, otherwise i have to open another camera and then have to call camera.takePicture().

So i want to use just scanner camera to capture the image.

rkistner commented 8 years ago

This is currently fairly complicated due to the way the Camera is used in a separate thread. Will look more into this later.

pablokvitca commented 8 years ago

Hello I'm trying to do this exact thing @rkistner Are there any updates on the matter? @Bajranghudda1 Where you able to find an alternative?

Bajranghudda1 commented 8 years ago

@pablokvitca Hi I'm calling camera using Camera api after closing scanner camera like this way

if(barcodeView.getBarcodeView().getCameraInstance().isOpen()) { barcodeView.getBarcodeView().getCameraInstance().close(); }

after this i'm calling another CameraActivity and doing all camera initializing and release stuff on onResume and onPause...

But i'm facing issue, because scanner could not able to release camera immediately,

I have to make it working till evening any how. If you have suggestion can help me.

pablokvitca commented 8 years ago

You wrote this just seconds (literally) after I found a solution! Of course, it's just a 'hack' solution. So it's not optimal, it's buggy, and kinda ugly. Still, it works. I added a button to the UI called "Save", and it simply calls this short code snippet:

barcodeView.getBarcodeView().getCameraInstance().requestPreview(new PreviewCallback() {
    @Override
    public void onPreview(SourceData sourceData) {
        sourceData.setCropRect(new Rect(0,0,500,500));
        Bitmap bmp = sourceData.getBitmap();
        try {
            File dir = new File(Environment.getExternalStorageDirectory().getPath().concat("/MyCaptureDirectory"));
            dir.mkdirs();

            String filepath = dir.getPath().concat(String.format("/%d.jpg", System.currentTimeMillis()));
            OutputStream stream = new FileOutputStream(filepath);
            bmp.compress(Bitmap.CompressFormat.JPEG, 100, stream);

            //Make a Toast with cream cheese
            Toast bagel = Toast.makeText(getApplicationContext(), "Saved!", Toast.LENGTH_SHORT);
            bagel.show();
        } catch (FileNotFoundException e) {
            Log.e(LOGTAG, e.getMessage());
        }
    }
});

Hope this helps you! Ask me if you have any questions on this!

P.S: Github Preview isn't working so I hope this code was inserted correctly.

Bajranghudda1 commented 8 years ago

@pablokvitca Hi Paul,

You are amazing, Let me check your solution. Any idea where it can failed? or not work well? Because i want a perfect image on button click (Save)

pablokvitca commented 8 years ago

@Bajranghudda1 Well, I am still trying to figure out how to make the picture not cropped. If you look at line 4 in the snippet, the bitmap needs a custom Rect, which I set to (0,0,500,500). This creates a 500x500 pixel picture. I am trying to figure out how to get the correct sizes from Android. Any ideas?

Bajranghudda1 commented 8 years ago

@pablokvitca Here is the way where we can find exact height and width of the currently opened barcode view

Log.d("Jugaduuu", "" + barcodeView.getBarcodeView().getMeasuredHeight() + " and " + barcodeView.getBarcodeView().getMeasuredWidth());

pablokvitca commented 8 years ago

@Bajranghudda1 Actually, I just got it. I'm not sure if the bitmap PreviewCallback uses fills 100% of the BarcodeView. Anyhow, this seems to work just fine:

sourceData.setCropRect(new Rect(0,0,sourceData.getDataHeight(), sourceData.getDataWidth()));

Note that the constructor is Rect(left, top, right, bottom). You need to use getDataHeight() for the right argument and and getDataWidth() for the bottom argument need to be inverted in order to work correctly.

Bajranghudda1 commented 8 years ago

@pablokvitca Okay i am going try your solution, Lets see how much it is efficient. I will update what i have done and how its efficiency. sourceData.getDataHeight(), sourceData.getDataWidth(), i think will give original height and width of viewing, right?

pablokvitca commented 8 years ago

Yes, and also it's all the data in the SourceData object. If you try to even 1 more pixel you get thrown an IllegalArgumentException "rectangle is not inside the image". Actually, now that I think about it, I should wrap this in a try-catch for that exception

Bajranghudda1 commented 8 years ago

@pablokvitca Thanks you for all the help and more importantly your precious time. Your efforts did work out and it's working fantastic :+1:

pablokvitca commented 8 years ago

Don't worry about it! We had to code the same thing after all!

On Fri, 12 Aug 2016, 02:00 Bajranghudda1, notifications@github.com wrote:

@pablokvitca https://github.com/pablokvitca Thanks you for all the help and more importantly your precious time. Your efforts did work out and it's working fantastic 👍

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/journeyapps/zxing-android-embedded/issues/183#issuecomment-239361354, or mute the thread https://github.com/notifications/unsubscribe-auth/ACDB3VPJIZwFavKcVnZXGZUafOX7KEBoks5qe_3kgaJpZM4JC-yc .

Pablo Kvitca pablokvitca@gmail.com

Bajranghudda1 commented 8 years ago

@pablokvitca I have one more query, if i want to see the captured image preview and if preview is okay then save the image.

I tried barcodeView.pause() on a button click and then calling the preview method, but we know here we paused the view already so the code barcodeView.getBarcodeView().getCameraInstance() will throw a NullPointerException

and i can't call barcodeView.pause on onPreview method (after crop the image) because it's not allowed on UI thread. ( java.lang.IllegalStateException: Must be called from the main thread.)

pablokvitca commented 8 years ago

Maybe you could try saving the image as is. And then opening the file on s different activity as an 'edit'. And deleting it if the user doesn't want it

On Fri, 12 Aug 2016, 03:17 Bajranghudda1, notifications@github.com wrote:

@pablokvitca https://github.com/pablokvitca I have one more query, if i want to see the captured image preview and if preview is okay then save the image.

I tried barcodeView.pause() on a button click and then calling the preview method, but we know here we paused the view already so the code barcodeView.getBarcodeView().getCameraInstance() will throw a NullPointerException

and i can't call barcodeView.pause on onPreview method (after crop the image) because it's not allowed on UI thread. ( java.lang.IllegalStateException: Must be called from the main thread.)

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/journeyapps/zxing-android-embedded/issues/183#issuecomment-239369367, or mute the thread https://github.com/notifications/unsubscribe-auth/ACDB3fh8owAdMuNRPzJyohiE8ViHwm83ks5qfA_3gaJpZM4JC-yc .

Pablo Kvitca pablokvitca@gmail.com

adamsythe commented 7 years ago

Hey guys thanks so much for this it worked great except pablokvitca i have found an issue when using it. The barcode scanner appears to sometimes turn off.

I have the barcode scanner running on decode continous, then the user presses save and it saves the image correctly, but then when they put the camera over a barcode it no longer detects the barcode.

pablokvitca commented 7 years ago

@adamsythe You need to reset it afterwards, that's the only solution I've found. "Have you tried turning it off and on again?"

adamsythe commented 7 years ago

Do you mean barcodeScanner.pause(); barcodeScanner.resume(); ?

pablokvitca commented 7 years ago

Yeah.

adamsythe commented 7 years ago

thanks that appears to work!

mxs2649 commented 7 years ago

Hello @Bajranghudda1

Can you please share the code to capture the image of only the preview rectangle area. I am trying to use the updated version but it does not seem to work properly.

s202394 commented 6 years ago

How can i take a picture only the preview rectangle area.

denizbas92 commented 5 years ago

You wrote this just seconds (literally) after I found a solution! Of course, it's just a 'hack' solution. So it's not optimal, it's buggy, and kinda ugly. Still, it works. I added a button to the UI called "Save", and it simply calls this short code snippet:

barcodeView.getBarcodeView().getCameraInstance().requestPreview(new PreviewCallback() {
    @Override
    public void onPreview(SourceData sourceData) {
        sourceData.setCropRect(new Rect(0,0,500,500));
        Bitmap bmp = sourceData.getBitmap();
        try {
            File dir = new File(Environment.getExternalStorageDirectory().getPath().concat("/MyCaptureDirectory"));
            dir.mkdirs();

            String filepath = dir.getPath().concat(String.format("/%d.jpg", System.currentTimeMillis()));
            OutputStream stream = new FileOutputStream(filepath);
            bmp.compress(Bitmap.CompressFormat.JPEG, 100, stream);

            //Make a Toast with cream cheese
            Toast bagel = Toast.makeText(getApplicationContext(), "Saved!", Toast.LENGTH_SHORT);
            bagel.show();
        } catch (FileNotFoundException e) {
            Log.e(LOGTAG, e.getMessage());
        }
    }
});

Hope this helps you! Ask me if you have any questions on this!

P.S: Github Preview isn't working so I hope this code was inserted correctly.

What is the

barcodeView.getBarcodeView().getCameraInstance().requestPreview(new PreviewCallback() { @Override public void onPreview(SourceData sourceData) { sourceData.setCropRect(new Rect(0,0,500,500)); Bitmap bmp = sourceData.getBitmap(); try { File dir = new File(Environment.getExternalStorageDirectory().getPath().concat("/MyCaptureDirectory")); dir.mkdirs(); String filepath = dir.getPath().concat(String.format("/%d.jpg", System.currentTimeMillis())); OutputStream stream = new FileOutputStream(filepath); bmp.compress(Bitmap.CompressFormat.JPEG, 100, stream); //Make a Toast with cream cheese Toast bagel = Toast.makeText(getApplicationContext(), "Saved!", Toast.LENGTH_SHORT); bagel.show(); } catch (FileNotFoundException e) { Log.e(LOGTAG, e.getMessage()); } } });

what is the barcodeView ??

rkistner commented 5 years ago

Closing as out of scope, although a pull request for this type of functionality would be welcome.

Note that if you only want the image from the scan, this is available on the BarcodeResult object.

ptorrent commented 4 years ago

Hello,

I hope you can help me...

When I do BarcodeResult.getBitmap() and then I convert it to base 64, this is what I have.. :

I can't get the full picture.

Do you have an idea ?

image

Your help would be greatly appreciated

rkistner commented 4 years ago

@ptorrent The data is most likely being truncated sometime after converting to base64. Make sure that if you are e.g. logging the base64 data, that it is not being cut off.

sece1024 commented 3 years ago

You wrote this just seconds (literally) after I found a solution! Of course, it's just a 'hack' solution. So it's not optimal, it's buggy, and kinda ugly. Still, it works. I added a button to the UI called "Save", and it simply calls this short code snippet:

barcodeView.getBarcodeView().getCameraInstance().requestPreview(new PreviewCallback() {
    @Override
    public void onPreview(SourceData sourceData) {
        sourceData.setCropRect(new Rect(0,0,500,500));
        Bitmap bmp = sourceData.getBitmap();
        try {
            File dir = new File(Environment.getExternalStorageDirectory().getPath().concat("/MyCaptureDirectory"));
            dir.mkdirs();

            String filepath = dir.getPath().concat(String.format("/%d.jpg", System.currentTimeMillis()));
            OutputStream stream = new FileOutputStream(filepath);
            bmp.compress(Bitmap.CompressFormat.JPEG, 100, stream);

            //Make a Toast with cream cheese
            Toast bagel = Toast.makeText(getApplicationContext(), "Saved!", Toast.LENGTH_SHORT);
            bagel.show();
        } catch (FileNotFoundException e) {
            Log.e(LOGTAG, e.getMessage());
        }
    }
});

Hope this helps you! Ask me if you have any questions on this!

P.S: Github Preview isn't working so I hope this code was inserted correctly.

It's usefull!

Raveen-AJ commented 2 years ago

You can simply enable TextureView and capture bitmap from that binding.qrScannerDecoratedBarcodeView.barcodeView.isUseTextureView = true val bitmap = (binding.qrScannerDecoratedBarcodeView.barcodeView[0] as TextureView).bitmap

oursdreams commented 7 months ago

You can simply enable TextureView and capture bitmap from that您只需启用 TextureView 并从中捕获位图 binding.qrScannerDecoratedBarcodeView.barcodeView.isUseTextureView = true val bitmap = (binding.qrScannerDecoratedBarcodeView.barcodeView[0] as TextureView).bitmap

Thank you! It's usefull!

barcodeView.getBarcodeView().setUseTextureView(true);
Bitmap bitmap = ((TextureView) barcodeView.getBarcodeView().getChildAt(0)).getBitmap();