I'm trying to process images captured from the preview using PreviewCallback, and am having problems with the conversion of YUV to RGB. I've tried the following approaches (most taken from answers here) and all give green and pink garbage images. None have worked for me so far, so am hoping someone can suggest a new approach.
Attempt 1:
private PreviewCallback previewCallback = new PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
YuvImage yuv = new YuvImage(data, previewFormat, previewSize.width, previewSize.height, null);
ByteArrayOutputStream out = new ByteArrayOutputStream();
yuv.compressToJpeg(new Rect(0, 0, yuv.getWidth(), yuv.getHeight()), 100, out);
byte[] bytes = out.toByteArray();
CamUtil.byteArrayToJPEG(MyActivity.this, bytes, "temp.jpg");
}
};
Attempt 2:
private PreviewCallback previewCallback = new PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
// functions below can be found easily on Stack Overflow
int[] rgb = decodeYUV420SP(data, previewSize.width, previewSize.height);
OR
int[] rgb = YUV_NV21_TO_RGB(data, previewSize.width, previewSize.height);
Bitmap bitmap = Bitmap.createBitmap(rgb, 0, previewSize.width, previewSize.width, previewSize.height, Bitmap.Config.ARGB_8888);
ByteArrayOutputStream out = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
byte[] bytes = out.toByteArray();
CamUtil.byteArrayToJPEG(View6Activity.this, bytes, "temp.jpg");
}
};
Attempt 3:
private PreviewCallback previewCallback = new PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
// after first setting previewFormat to RGB_565
Bitmap bitmap = Bitmap.createBitmap(previewSize.width, previewSize.height, Bitmap.Config.RGB_565);
ByteBuffer buffer = ByteBuffer.wrap(data);
bitmap.copyPixelsFromBuffer(buffer);
ByteArrayOutputStream out = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
byte[] bytes = out.toByteArray();
CamUtil.byteArrayToJPEG(View6Activity.this, bytes, "temp.jpg");
}
};
Attempt 4 (from Converting YUV->RGB(Image processing)->YUV during onPreviewFrame in android?)
private PreviewCallback previewCallback = new PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
int imageWidth = previewSize.width;
int imageHeight = previewSize.height;
// the bitmap we want to fill with the image
Bitmap bitmap = Bitmap.createBitmap(imageWidth, imageHeight, Bitmap.Config.ARGB_8888);
int numPixels = imageWidth*imageHeight;
// the buffer we fill up which we then fill the bitmap with
IntBuffer intBuffer = IntBuffer.allocate(imageWidth*imageHeight);
// If you're reusing a buffer, next line imperative to refill from the start,
// if not good practice
intBuffer.position(0);
// Set the alpha for the image: 0 is transparent, 255 fully opaque
final byte alpha = (byte) 255;
// Get each pixel, one at a time
for (int y = 0; y < imageHeight; y++) {
for (int x = 0; x < imageWidth; x++) {
// Get the Y value, stored in the first block of data
// The logical "AND 0xff" is needed to deal with the signed issue
int Y = data[y*imageWidth + x] & 0xff;
// Get U and V values, stored after Y values, one per 2x2 block
// of pixels, interleaved. Prepare them as floats with correct range
// ready for calculation later.
int xby2 = x/2;
int yby2 = y/2;
float U = (float)(data[numPixels + 2*xby2 + yby2*imageWidth] & 0xff) - 128.0f;
float V = (float)(data[numPixels + 2*xby2 + 1 + yby2*imageWidth] & 0xff) - 128.0f;
// Do the YUV -> RGB conversion
float Yf = 1.164f*((float)Y) - 16.0f;
int R = (int)(Yf + 1.596f*V);
int G = (int)(Yf - 0.813f*V - 0.391f*U);
int B = (int)(Yf + 2.018f*U);
// Clip rgb values to 0-255
R = R < 0 ? 0 : R > 255 ? 255 : R;
G = G < 0 ? 0 : G > 255 ? 255 : G;
B = B < 0 ? 0 : B > 255 ? 255 : B;
// Put that pixel in the buffer
intBuffer.put(alpha*16777216 + R*65536 + G*256 + B);
}
}
// Get buffer ready to be read
intBuffer.flip();
// Push the pixel information from the buffer onto the bitmap.
bitmap.copyPixelsFromBuffer(intBuffer);
ByteArrayOutputStream out = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
byte[] bytes = out.toByteArray();
CamUtil.byteArrayToJPEG(View6Activity.this, bytes, "temp.jpg");
}
};
All these approaches are giving me green and pink garbage images. Can anyone help?