3

I am trying to get a Bitmap Image from Camera Preview on which I am going to do some processing and draw some overlays after performing Face detection.

After looking around, I found out that the byte array that onPreviewFrame takes cannot be decoded into a bitmap directly, it needs to be converted to the correct pixel format using YuvImage, and that's exactly what I did:

@Override
public void onPreviewFrame(byte[] data, Camera camera)
{
    YuvImage temp = new YuvImage(data, camera.getParameters().getPreviewFormat(), camera.getParameters().getPictureSize().width, camera.getParameters().getPictureSize().height, null);

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    temp.compressToJpeg(new Rect(0, 0, temp.getWidth(), temp.getHeight()), 80, os);

    Bitmap preview = BitmapFactory.decodeByteArray(os.toByteArray(), 0, os.toByteArray().length);

    /* DO SOMETHING WITH THE preview */

}

The problem is, the 'preview' object is not null, but it's aparently not a valid Bitmap. On the debugger I can see that mWidth and mHeight are both set to -1 which seems wrong to me. What am I doing wrong?

Francois Zard
  • 341
  • 3
  • 11
  • If you are drawing overlays and doing heavy things like face detectino, you are going to want to speed of the NDK. Take a look at GLSurfaceView and how it can be used with callbacks. You won't want a jpeg - do your operations on the native byte array – Andrew G Oct 08 '12 at 18:44
  • @AndrewG, how do you get an image frame as a `Bitmap` when using a `GLSurfaceView`. – Sam Dec 06 '14 at 23:44

3 Answers3

1

On API level 8 or higher you can compress the images very quickly to JPEG using the following code.

public void onPreviewFrame(byte[] data, Camera arg1) {
    FileOutputStream outStream = null;
    try {
        YuvImage yuvimage = new YuvImage(data,ImageFormat.NV21,arg1.getParameters().getPreviewSize().width,arg1.getParameters().getPreviewSize().height,null);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        yuvimage.compressToJpeg(new Rect(0,0,arg1.getParameters().getPreviewSize().width,arg1.getParameters().getPreviewSize().height), 80, baos);

        outStream = new FileOutputStream(String.format("/sdcard/%d.jpg", System.currentTimeMillis()));  
        outStream.write(baos.toByteArray());
        outStream.close();

        Log.d(TAG, "onPreviewFrame - wrote bytes: " + data.length);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
    }
    Preview.this.invalidate();
}

From https://code.google.com/p/android/issues/detail?id=823#c37

TalkLittle
  • 8,866
  • 6
  • 54
  • 51
0

There's a detailed information about your issue here: https://code.google.com/p/android/issues/detail?id=823

ZeoS
  • 72
  • 1
  • 5
0

You're using getPictureSize instead of getPreviewSize :)

Truelle
  • 61
  • 3