Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert bitmap array to YUV (YCbCr NV21)

How to convert Bitmap returned by BitmapFactory.decodeFile() to YUV format (simillar to what camera's onPreviewFrame() returns in byte array)?

like image 505
Abhijeet Pathak Avatar asked May 11 '11 06:05

Abhijeet Pathak


2 Answers

Here is some code that actually works:

    // untested function     byte [] getNV21(int inputWidth, int inputHeight, Bitmap scaled) {          int [] argb = new int[inputWidth * inputHeight];          scaled.getPixels(argb, 0, inputWidth, 0, 0, inputWidth, inputHeight);          byte [] yuv = new byte[inputWidth*inputHeight*3/2];         encodeYUV420SP(yuv, argb, inputWidth, inputHeight);          scaled.recycle();          return yuv;     }      void encodeYUV420SP(byte[] yuv420sp, int[] argb, int width, int height) {         final int frameSize = width * height;          int yIndex = 0;         int uvIndex = 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[uvIndex++] = (byte)((V<0) ? 0 : ((V > 255) ? 255 : V));                     yuv420sp[uvIndex++] = (byte)((U<0) ? 0 : ((U > 255) ? 255 : U));                 }                  index ++;             }         }     } 
like image 120
Fracdroid Avatar answered Sep 19 '22 15:09

Fracdroid


Following is the code for converting Bitmap to Yuv(NV21) Format.

void yourFunction(){      // mBitmap is your bitmap      int mWidth = mBitmap.getWidth();     int mHeight = mBitmap.getHeight();      int[] mIntArray = new int[mWidth * mHeight];      // Copy pixel data from the Bitmap into the 'intArray' array     mBitmap.getPixels(mIntArray, 0, mWidth, 0, 0, mWidth, mHeight);      // Call to encoding function : convert intArray to Yuv Binary data     encodeYUV420SP(data, intArray, mWidth, mHeight);  }  static public void encodeYUV420SP(byte[] yuv420sp, int[] rgba,         int width, int height) {     final int frameSize = width * height;      int[] U, V;     U = new int[frameSize];     V = new int[frameSize];      final int uvwidth = width / 2;      int r, g, b, y, u, v;     for (int j = 0; j < height; j++) {         int index = width * j;         for (int i = 0; i < width; i++) {              r = Color.red(rgba[index]);             g = Color.green(rgba[index]);             b = Color.blue(rgba[index]);              // rgb to yuv             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;              // clip y             yuv420sp[index] = (byte) ((y < 0) ? 0 : ((y > 255) ? 255 : y));             U[index] = u;             V[index++] = v;         }     } 
like image 24
Hitesh Patel Avatar answered Sep 18 '22 15:09

Hitesh Patel