package com.whyc.util; import android.media.Image; public class YUVUtil { public static void YUVToNV21_NV12(Image image, byte[] nv21, int w, int h, String type) { Image.Plane[] planes = image.getPlanes(); int remaining0 = planes[0].getBuffer().remaining(); int remaining1 = planes[1].getBuffer().remaining(); int remaining2 = planes[2].getBuffer().remaining(); //分别准备三个数组接收YUV分量。 byte[] yRawSrcBytes = new byte[remaining0]; byte[] uRawSrcBytes = new byte[remaining1]; byte[] vRawSrcBytes = new byte[remaining2]; planes[0].getBuffer().get(yRawSrcBytes); planes[1].getBuffer().get(uRawSrcBytes); planes[2].getBuffer().get(vRawSrcBytes); int j = 0, k = 0; boolean flag = type.equals("NV21"); if (type.equals("NV21") || type.equals("NV12")) { for (int i = 0; i < nv21.length; i++) { if (i < w * h) { //首先填充w*h个Y分量 nv21[i] = yRawSrcBytes[i]; } else { if (flag) { //若NV21类型 则Y分量分配完后第一个将是V分量 nv21[i] = vRawSrcBytes[j]; //PixelStride有用数据步长 = 1紧凑按顺序填充,=2每间隔一个填充数据 j += planes[1].getPixelStride(); } else { //若NV12类型 则Y分量分配完后第一个将是U分量 nv21[i] = uRawSrcBytes[k]; //PixelStride有用数据步长 = 1紧凑按顺序填充,=2每间隔一个填充数据 k += planes[2].getPixelStride(); } //紧接着可以交错UV或者VU排列不停的改变flag标志即可交错排列 flag = !flag; } } }else{ //I420标准结构Plannar,YUV分量首先存放w * h 个Y,接着存放 w * h * 0.25 个U最后存放 w * h * 0.25 个V for (int i = 0; i < nv21.length; i++) { if (i < w * h) { //首先填充w*h个Y分量 nv21[i] = yRawSrcBytes[i]; } else if (i < w * h * 5 / 4) { nv21[i] = uRawSrcBytes[j]; j += planes[1].getPixelStride(); } else { nv21[i] = vRawSrcBytes[k]; k += planes[2].getPixelStride(); } } } } }