1,Camera基本调用流程
android相机基本使用流程CameraManager:管理所有的摄像头(CameraDevice)设备的管理者,打开摄像头等功能。
CameraDevice:一个手机设备一般有两个摄像头(CameraDevice),前置和后置。该类通过CameraCharacteristics对象提供摄像头的硬件信息,配置信息和输出参数等。
2,图像相关概念
YUV类型
YUV 4:4:4采样,每一个Y对应一组UV分量。
YUV 4:2:2采样,每两个Y共用一组UV分量。
YUV 4:2:0采样,每四个Y共用一组UV分量。
我们可以通过y和uv数据量大小的比值,来判断采样类型。
同为YUV420,也有不同的数据存放形式,形成了不同的数据类型:
Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
U U U U U U V V V V V V U V U V U V V U V U V U
V V V V V V U U U U U U U V U V U V V U V U V U
- I420 - - YV12 - - NV12 - - NV21 -
YUV中的plane和stride
plane指描述像素点的所有信息维度。比如RGB格式就有三个plane分别为R、G、B。YUV的话也是三个,y、u和v。
Image.getPlanes(); //获取图像所有的planes数据
stride指在内存中每行像素所占的空间。如下图所示,为了实现内存对齐(或者其它的什么原因),每行像素在内存中所占的空间并不是图像的宽度。
Image.getPlanes()[0].getRowStride(); //从Plane中获取stride
图像类型转换
YUV_420_888表示YUV420格式的集合,888表示Y、U、V分量中每个像素点占8bit(1Byte)。我们通过Camera获取的时候它是没有指具体的格式的,只是通过ImageReader给了我们y,u,v三个plane,我们可以自己将它组装成特定的YUV数据。
//组装NV21图像
public static byte[] yuv420ToNv21(byte[] y, byte[] u, byte[] v) {
Byte[] nv21 = new Byte[y.length+u.length+v.length];
//先组装y数据
System.arrayCopy(y,0,nv21,0,y.length);
int uIndex = 0;
int vIndex = 0;
//开始组装uv数据
for(int i=y.length;i<nv21.length;i++) {
nv21[i] = v[vIndex++];
nv21[i+1] = u[uIndex++];
}
}
//将nv21转换为YuvImage
YuvImage yuvImage = new YuvImage(nv21, ImageFormat.NV21, stride, height, null);
//转为jpeg
yuvImage.compressToJpeg(new Rect(0, 0, previewSize.getWidth(), previewSize.getHeight()), 100, byteArrayOutputStream);
byte[] jpgBytes = byteArrayOutputStream.toByteArray();
//生成bitmap
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
final Bitmap originalBitmap = BitmapFactory.decodeByteArray(jpgBytes, 0, jpgBytes.length, options);
参考代码
https://github.com/nicochofly/Test4Camera2
https://github.com/wangshengyang1996/Camera2Demo
网友评论