已经有很多文章介绍Image对象,这里不再多解释.
写在这里一是为了做个笔记记录,二是查了好多资料确实没有找到YUV_420_888转换YUYV的方法,希望帮助更多人吧.
public static byte[] getYUYVFromImage420(Image image) {
try {
//获取源数据,如果是YUV格式的数据planes.length = 3
//plane[i]里面的实际数据可能存在byte[].length <= capacity (缓冲区总大小)
final Image.Plane[] planes = image.getPlanes();
//数据有效宽度,一般的,图片width <= rowStride,这也是导致byte[].length <= capacity的原因
//所以我们只取width部分
int width = image.getWidth();
int height = image.getHeight();
//此处用来装填最终的YUV数据,需要2倍的图片大小,因为Y U V 比例为 4:2:2
byte[] yuvBytes = new byte[width * height * ImageFormat.getBitsPerPixel(ImageFormat.YUV_422_888) / 8];
//临时存储y u v数据的
byte[] yBytes = new byte[width * height];
//--分离Y数据
ByteBuffer buffer = planes[0].getBuffer();
buffer.get(yBytes);
int uPixelsStride, vPixelsStride;
//--分离U数据
uPixelsStride = planes[1].getPixelStride();
buffer = planes[1].getBuffer();
byte[] uTempBytes = new byte[buffer.capacity()];
buffer.get(uTempBytes);
vPixelsStride = planes[2].getPixelStride();
//--分离V数据
buffer = planes[2].getBuffer();
byte[] vTempBytes = new byte[buffer.capacity()];
buffer.get(vTempBytes);
int ySrcIndex = 0;
int uSrcIndex = 0;
int vSrcIndex = 0;
int yDstIndex = 0;
for (int j = 0; j < height / 2; j++) {
int uvWidth = width;
for (int k = 0; k < uvWidth / 2; k++) {
// Y
yuvBytes[yDstIndex] = yBytes[ySrcIndex];
yuvBytes[yDstIndex + uvWidth * 2] = yBytes[ySrcIndex + uvWidth];
yDstIndex++;
ySrcIndex++;
// U
yuvBytes[yDstIndex] = uTempBytes[uSrcIndex];
yuvBytes[yDstIndex + uvWidth * 2] = uTempBytes[uSrcIndex];
yDstIndex++;
// Y
yuvBytes[yDstIndex] = yBytes[ySrcIndex];
yuvBytes[yDstIndex + uvWidth * 2] = yBytes[ySrcIndex + uvWidth];
yDstIndex++;
ySrcIndex++;
// V
yuvBytes[yDstIndex] = vTempBytes[vSrcIndex];
yuvBytes[yDstIndex + uvWidth * 2] = vTempBytes[vSrcIndex];
yDstIndex++;
uSrcIndex += uPixelsStride;
vSrcIndex += vPixelsStride;
}
yDstIndex += uvWidth * 2;
ySrcIndex += uvWidth;
}
image.close();
return yuvBytes;
} catch (final Exception e) {
if (image != null) {
image.close();
}
Log.e("ArMn", android.util.Log.getStackTraceString(e));
}
return null;
}