2

So I have this camera preview set up with Camera, SurfaceView and SurfaceHolder. I have also an ImageView where I will be putting a modified version of the camera image and I want this to update lets say once every second.

All code is ready and already working when I load images from "res" but I have a really hard time reading the image data from the camera.

I've tried following already:

  1. Creating an intent for MediaStore.ACTION_IMAGE_CAPTURE and starting an onActivityResult getting a small thumbnail (enough for me actually) from (Bitmap)data.getExtras().get("data")

    The problem is that this opens the camera App and you need to "manually" take a picture.

  2. Creating a Camera.PreviewCallback, taking the YuvImage, and converting it to an image using YuvImage.compressToJpeg(...).

    The problem here is that I can't get it to start no matter when or where i put the Camera.setPreviewCallbackWithBuffer(PreviewCallback).

  3. Try to take the data directly from PreviewHolder by locking in to the canvas using lockCanvas() and trying to convert it to a bitmap

    Obviously Doesn't work.

Edit: What is the best way to make this work? I mean QR-Code readers must read the image data out of the camera continuously, how do they work?

Eddie Cheng
  • 171
  • 2
  • 9
  • 1
    Check out how ZXing does it. https://code.google.com/p/zxing/source/browse/trunk#trunk%2Fandroid%2Fsrc%2Fcom%2Fgoogle%2Fzxing%2Fclient%2Fandroid – Krylez Nov 20 '13 at 23:20

1 Answers1

5

I went for option number 2 and finally made it work.

used this callback, forgot the @Override before

private Camera.PreviewCallback  previewCallback= new Camera.PreviewCallback()
{   
    @Override
    public void onPreviewFrame(byte[] data,Camera cam)
    {
            Camera.Size previewSize = cam.getParameters().getPreviewSize();
            YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21,previewSize.width,previewSize.height, null);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            yuvImage.compressToJpeg(new Rect(0,0,previewSize.width,previewSize.height),80,baos);
            byte[] jdata = baos.toByteArray();
            Bitmap bitmap = BitmapFactory.decodeByteArray(jdata,0,jdata.length);    
    }
};

And initiating it using setPreviewCallback rather than setPreviewCallbackWithBuffer

SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback() 
{   
    public void surfaceCreated(SurfaceHolder holder) {

        camera.setPreviewCallback(previewCallback);
    }
}
Eddie Cheng
  • 171
  • 2
  • 9
  • 1
    This might have a bug in it; it assumes the image format is `NV21`. It might be more robust to read the image format out of `cam.getParameters().getPreviewFormat()`. – Sam Dec 06 '14 at 23:37
  • Actually, never mind. According to `YuvImage`'s javadoc, it only supports NV21 and YUV2, whereas the camera is only guaranteed across all devices to support NV21, which is the default anyway, and YV12. So NV21 is the only reliable option. – Sam Dec 07 '14 at 00:08