Search code examples
androidimagecamerapreviewyuv

Android YuvImage class format incorrect?


It's well documented that Android's camera preview data is returned back in NV21 (YUV 420). 2.2 added a YuvImage class for decoding the data. The problem I've encountered is that the YuvImage class data appears corrupt or incorrect. I used the Renderscript Sample app called HelloCompute which transforms a Bitmap into a mono-chrome Bitmap. I used two methods for decoding the Preview data into a Bitmap and passing it as input to the Renderscript:

Method 1 - Android YuvImage Class:

YuvImage preview = new YuvImage(data, ImageFormat.NV21, width, height, null);

ByteArrayOutputStream mJpegOutput = new ByteArrayOutputStream(data.length); 

preview.compressToJpeg(new Rect(0, 0, width, height), 100, mJpegOutput);
mBitmapIn = BitmapFactory.decodeByteArray( mJpegOutput.toByteArray(), 0, mJpegOutput.size());

// pass mBitmapIn to RS

Method 2 - Posted Decoder Method: As posted over here by David Pearlman

// work around for Yuv format </p>
mBitmapIn = Bitmap.createBitmap(
      ImageUtil.decodeYUV420SP(data, width, height),
      width, 
      height, 
      Bitmap.Config.ARGB_8888);

// pass mBitmapIn to RS

When the image is processed by the Renderscript and displayed Method 1 is very grainy and not mono-chrome, while Method 2 produces the expected output, a mono-chrome image of the preview frame. Am I doing something wrong or is the YuvImage class not usable? I'm testing this on a Xoom running 3.1.

Furthermore, I displayed the bitmaps produced by both methods on screen prior to passing to the RS. The bitmap from Method 1 has noticeable differences in lighting (I suspected this was due to the JPeg compression), while Method 2's bitmap is identical to the Preview Frame.


Solution

  • There is no justification for using Jpeg encode/decode just to convert a YUV image to a grayscale bitmap (I believe you want grayscale, not monochrome b/w bitmap after all). You can find many code samples that produce the result you need. You may use this one: Converting preview frame to bitmap.