Convert Bitmap Array to Yuv (Ycbcr Nv21)

Convert bitmap array to YUV (420planar)?

A bit of reading into YUV formats helped me figure it out. I just had to modify a tiny bit of the code linked above. For anyone who has the same doubt

void encodeYUV420SP(byte[] yuv420sp, int[] argb, int width, int height) {
final int frameSize = width * height;

int yIndex = 0;
int uIndex = frameSize;
int vIndex = frameSize+((yuv420sp.length-frameSize)/2);
System.out.println(yuv420sp.length+" "+frameSize);


int a, R, G, B, Y, U, V;
int index = 0;
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {

a = (argb[index] & 0xff000000) >> 24; // a is not used obviously
R = (argb[index] & 0xff0000) >> 16;
G = (argb[index] & 0xff00) >> 8;
B = (argb[index] & 0xff) >> 0;

// well known RGB to YUV algorithm

Y = ( ( 66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
U = ( ( -38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
V = ( ( 112 * R - 94 * G - 18 * B + 128) >> 8) + 128;

// NV21 has a plane of Y and interleaved planes of VU each sampled by a factor of 2
// meaning for every 4 Y pixels there are 1 V and 1 U. Note the sampling is every other
// pixel AND every other scanline.
yuv420sp[yIndex++] = (byte) ((Y < 0) ? 0 : ((Y > 255) ? 255 : Y));
if (j % 2 == 0 && index % 2 == 0) {
yuv420sp[uIndex++] = (byte)((U<0) ? 0 : ((U > 255) ? 255 : U));
yuv420sp[vIndex++] = (byte)((V<0) ? 0 : ((V > 255) ? 255 : V));
}

index ++;
}
}
}

How can I convert android bitmap to NV12 color format?

Replace

a = (argb[index] & 0xff000000) >> 24; // a is not used obviously
R = (argb[index] & 0xff0000) >> 16;
G = (argb[index] & 0xff00) >> 8;
B = (argb[index] & 0xff) >> 0;

with,

R = (argb[index] & 0xff000000) >>> 24;
G = (argb[index] & 0xff0000) >> 16;
B = (argb[index] & 0xff00) >> 8;

Down scale issue on NV21 - ARGB - NV21 conversion

I finally end up resizing my image (as a OpenCV.Mat) directly in C++. This was way easier and faster.

Size size(correctedWidth, correctedHeight);
Mat dst;
resize(image, dst, size);

Android ImageReader get NV21 format?

Generally speaking, the point of ImageReader is to give you raw access to the pixels sent to the Surface with minimal overhead, so attempting to have it perform color conversions doesn't make sense.

For the Camera you get to pick one of two output formats (NV21 or YV12), so pick YV12. That's your raw YUV data. For screen capture the output will always be RGB, so you need to pick RGBA_8888 (format 0x1) for your ImageReader, rather than YUV_420_888 (format 0x23). If you need YUV for that, you will have to do the conversion yourself. The ImageReader gives you a series of Plane objects, not a byte[], so you will need to adapt to that.

Obtain/convert to YCbCr_420_SP (NV21) image format from Camera API function takePicture()

There are two ways to improve your result.

  • You can use jpeg-turbo library to obtain YUV from Jpeg directly, the function is tjDecompressToYUV.

  • You can use renderscript to convert bitmaps to YUV.

Which one will be better for you, depends on the device. Some will have hardware-accelerated Jpeg decoder for Java, some will use libjpeg in software. In the latter case, tjDecompressToYUV will deliver a significant improvement.

If your device runs Android-5 or higher, consider switching to the camera2 API, ImageReader may be able to deliver YUV or RAW images of desired resolution and quality.

Android RGB to YCbCr Conversion and output to imageView

Try setting using below code

ByteArrayOutputStream out = new ByteArrayOutputStream();
YuvImage yuvImage = new YuvImage(your_yuv_data, ImageFormat.NV21, width, height, null);
yuvImage.compressToJpeg(new Rect(0, 0, width, height), 50, out);
byte[] imageBytes = out.toByteArray();
Bitmap image = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
iv.setImageBitmap(image);

Check documentation for detailed description for YuvImage Class.



Related Topics



Leave a reply



Submit