最近在搞视频分析类的项目,android默认视频采集格式是NV21,Y Cr Cb格式,4.2.0.方式采样

还有其他采样方式,默认使用NV21

Sets the image format for preview pictures.

If this is never called, the default format will be NV21, which uses the NV21 encoding format.

int JPEG Encoded formats.
int NV16 YCbCr format, used for video.
int NV21 YCrCb format used for images, which uses the NV21 encoding format.
int RGB_565 RGB format used for pictures encoded as RGB_565 see setPictureFormat(int).
int UNKNOWN  
int YUY2 YCbCr format used for images, which uses YUYV (YUY2) encoding format.
int YV12 Android YUV format: This format is exposed to software decoders and applications.
具体参见 http://developer.android.com/reference/android/graphics/ImageFormat.html ----------------------------------------------------------------------------------------------------------- 首先是其数据是怎样存储的 // 我们通过下列方式获取数据 class Buf implements Camera.PreviewCallback { public byte[] yuv420sp =null; public void onPreviewFrame(byte[] data, Camera camera) { // 这里出来的data和tackPic出来的有区别,这边是NV21格式 yuv420sp=data; } } 420这种格式采样方式如下 X  X  X  X O     O    X  X  X  X
X  X  X  X O     O    X  X  X  X 即每4个Y对应一个U和一个V Y0U0V0             Y1                 Y2U2V2                Y3 Y4                       Y5                 Y6                          Y7 Y8U8V8             Y9                 Y10U10V10         Y11 Y12                     Y13               Y14                       Y15 通过对采样数组的研究其存放规律是 YYYYY...(采样宽度width)...YYYYY ... ...(采样高度height) ... YYYYY...(采样宽度width)...YYYYY (vu)(vu)(vu)...(采样宽度)...(vu)(vu)(vu) ...(采样高度除以2,height/2,遇单加1) (vu)(vu)(vu)...(采样宽度)...(vu)(vu)(vu) 即width=320,height=480,采样Y值长度320×480,采样VU长度320×480/2.yuv420sp=data;总长度为宽高乘积的一点五倍
// YUV转RGB rgb长度即width×heght static public void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width, int height) {         final int frameSize = width * height;                  for (int j = 0, yp = 0; j < height; j++) {                 int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;                 for (int i = 0; i < width; i++, yp++) {                         int y = (0xff & ((int) yuv420sp[yp])) - 16;                         if (y < 0) y = 0;                         if ((i & 1) == 0) {                                 v = (0xff & yuv420sp[uvp++]) - 128;                                 u = (0xff & yuv420sp[uvp++]) - 128;                         }                                                  int y1192 = 1192 * y;                         int r = (y1192 + 1634 * v);                         int g = (y1192 - 833 * v - 400 * u);                         int b = (y1192 + 2066 * u);                                                  if (r < 0) r = 0; else if (r > 262143) r = 262143;                         if (g < 0) g = 0; else if (g > 262143) g = 262143;                         if (b < 0) b = 0; else if (b > 262143) b = 262143;                                                  rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);                 }         } }
以上是android自带的YUV420SP转RGB的函数,但是坑爹的问题在于函数处理数据的能力有限,我们有的时候并不需要全部转完毕再解析。 以下是更改后的方法,用于取值某点的RGB,在一些实时性要求的应用中可以用到 // 自定义RGB static public int myDecodeYUV420SP(byte[] yuv420sp, int width, int height, int mWidth, int mHeight) { // Y矩阵长度frameSize , V和U矩阵第一位即frameSize final int frameSize = width * height; // yp为Y在矩阵中的位置,yph为所需要点的高mHeight-1,ypw为所需要点的宽mWidth int yp, yph = mHeight - 1, ypw = mWidth; yp = width * yph + ypw; // uvp为 // uv在数组中的位置,V和U矩阵第一位即frameSize,yph>>1取值范围(0,0,1,1,2,2...)yph从0开始,即UV数组为Y数组的1/2. int uvp = frameSize + (yph >> 1) * width, u = 0, v = 0; // 获取Y的数值 int y = (0xff & ((int) yuv420sp[yp])) - 16; if (y < 0) y = 0; if ((ypw & 1) == 0) { v = (0xff & yuv420sp[uvp++]) - 128; u = (0xff & yuv420sp[uvp]) - 128; } else { u = (0xff & yuv420sp[uvp--]) - 128; v = (0xff & yuv420sp[uvp]) - 128; }
int y1192 = 1192 * y; int r = (y1192 + 1634 * v); int g = (y1192 - 833 * v - 400 * u); int b = (y1192 + 2066 * u);
if (r < 0) r = 0; else if (r > 262143) r = 262143; if (g < 0) g = 0; else if (g > 262143) g = 262143; if (b < 0) b = 0; else if (b > 262143) b = 262143;
return (0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff));
}
两套函数出来的数据int型需要转换成r/g/b。亮点就是转换方式

public static int red (int color)

Since:  API Level 1

Return the red component of a color int. This is the same as saying (color >> 16) & 0xFF

public static int green (int color)

Since:  API Level 1

Return the green component of a color int. This is the same as saying (color >> 8) & 0xFF

public static int blue (int color)

Since:  API Level 1

Return the blue component of a color int. This is the same as saying color & 0xFF

至此yuv取点rgb完成 1 需要代码的童鞋可以留下你的email 2 如果描述有误请指正 3 感谢 幸福的起点 博主,更多视频格式说明请参照 http://hi.baidu.com/joygogo0130/blog/item/04b707529efbec090df3e345.html 4 更多视频问题 请参照 http://developer.android.com/reference/android/graphics/Camera.html http://ai4work.blog.163.com/blog/static/189873306201171883316264/

更多相关文章

  1. android 发送短信的两种方式,以及接收报告和发送报告
  2. Android解析XML的三种方式
  3. Android并发编程线程间通信的三种基本方式
  4. Android中测量Text的宽度和高度
  5. Android获取CPU使用率的几种方式
  6. android中activity的启动方式
  7. Android 数据存储方式
  8. Android 文件打开方式

随机推荐

  1. android 开发BUG
  2. Android中事件分发机制分析
  3. Android下基于XML的Graphics shape使用方
  4. 【Android学习入门】Android studio基本
  5. dev android project from cmd
  6. Android google地图开发的前期准备(MD5和
  7. Android(安卓)图片平铺效果
  8. android技术开发例子,解析以及源码集锦
  9. android LinearLayout布局子空间没有填充
  10. android 获取控件真实高度