万众城网站建设,建网站金坛哪家强?,WordPress发不出注册邮箱,c 做游戏的网站教学目录
java imagereader编码保存
java NV21toYUV420SemiPlanar 编码保存视频用#xff1a;
imageReader获取nv21 代码来自博客#xff1a;
【Android Camera2】彻底弄清图像数据YUV420_888转NV21问题/良心教学/避坑必读!_yuv420888转nv21_奔跑的鲁班七号的博客-CSDN博客
…目录
java imagereader编码保存
java NV21toYUV420SemiPlanar 编码保存视频用
imageReader获取nv21 代码来自博客
【Android Camera2】彻底弄清图像数据YUV420_888转NV21问题/良心教学/避坑必读!_yuv420888转nv21_奔跑的鲁班七号的博客-CSDN博客
java imagereader编码保存
//Planar格式P的处理private static ByteBuffer getuvBufferWithoutPaddingP(ByteBuffer uBuffer,ByteBuffer vBuffer, int width, int height, int rowStride, int pixelStride){int pos 0;byte []byteArray new byte[height*width/2];for (int row0; rowheight/2; row) {for (int col0; colwidth/2; col) {int vuPos col*pixelStride row*rowStride;byteArray[pos] vBuffer.get(vuPos);byteArray[pos] uBuffer.get(vuPos);}}ByteBuffer bufferWithoutPaddingsByteBuffer.allocate(byteArray.length);// 数组放到buffer中bufferWithoutPaddings.put(byteArray);//重置 limit 和postion 值否则 buffer 读取数据不对bufferWithoutPaddings.flip();return bufferWithoutPaddings;}//Semi-Planar格式SP的处理和y通道的数据private static ByteBuffer getBufferWithoutPadding(ByteBuffer buffer, int width, int rowStride, int times,boolean isVbuffer){if(width rowStride) return buffer; //没有buffer,不用处理。int bufferPos buffer.position();int cap buffer.capacity();byte []byteArray new byte[times*width];int pos 0;//对于y平面要逐行赋值的次数就是height次。对于uv交替的平面赋值的次数是height/2次for (int i0;itimes;i) {buffer.position(bufferPos);//part 1.1 对于u,v通道,会缺失最后一个像u值或者v值因此需要特殊处理否则会crashif(isVbuffer itimes-1){width width -1;}buffer.get(byteArray, pos, width);bufferPos rowStride;pos poswidth;}//nv21数组转成buffer并返回ByteBuffer bufferWithoutPaddingsByteBuffer.allocate(byteArray.length);// 数组放到buffer中bufferWithoutPaddings.put(byteArray);//重置 limit 和postion 值否则 buffer 读取数据不对bufferWithoutPaddings.flip();return bufferWithoutPaddings;}private static byte[] YUV_420_888toNV21(Image image) {int width image.getWidth();int height image.getHeight();ByteBuffer yBuffer getBufferWithoutPadding(image.getPlanes()[0].getBuffer(), image.getWidth(), image.getPlanes()[0].getRowStride(),image.getHeight(),false);ByteBuffer vBuffer;//part1 获得真正的消除padding的ybuffer和ubuffer。需要对P格式和SP格式做不同的处理。如果是P格式的话只能逐像素去做性能会降低。if(image.getPlanes()[2].getPixelStride()1){ //如果为true说明是P格式。vBuffer getuvBufferWithoutPaddingP(image.getPlanes()[1].getBuffer(), image.getPlanes()[2].getBuffer(),width,height,image.getPlanes()[1].getRowStride(),image.getPlanes()[1].getPixelStride());}else{vBuffer getBufferWithoutPadding(image.getPlanes()[2].getBuffer(), image.getWidth(), image.getPlanes()[2].getRowStride(),image.getHeight()/2,true);}//part2 将y数据和uv的交替数据除去最后一个v值赋值给nv21int ySize yBuffer.remaining();int vSize vBuffer.remaining();byte[] nv21;int byteSize width*height*3/2;nv21 new byte[byteSize];yBuffer.get(nv21, 0, ySize);vBuffer.get(nv21, ySize, vSize);//part3 最后一个像素值的u值是缺失的因此需要从u平面取一下。ByteBuffer uPlane image.getPlanes()[1].getBuffer();byte lastValue uPlane.get(uPlane.capacity() - 1);nv21[byteSize - 1] lastValue;return nv21;}java NV21toYUV420SemiPlanar 编码保存视频用 public byte[] NV21toYUV420SemiPlanar(byte[] nv21, int width, int height) {byte[] yuv420sp new byte[width * height * 3 / 2];int frameSize width * height;int i, j;System.arraycopy(nv21, 0, yuv420sp, 0, frameSize); // Y分量直接复制for (i 0; i frameSize / 4; i) {j i * 2;// NV21的UV分量交替排列转为NV12需要调换U和V的位置yuv420sp[frameSize j] nv21[frameSize j 1]; // U分量yuv420sp[frameSize j 1] nv21[frameSize j]; // V分量}return yuv420sp;} imageReader获取nv21
plane[0] plane[2] NV21;; plane[0] plane[1] NV12
Image image reader.acquireLatestImage();
if (image null) {return;
}Image.Plane[] planes image.getPlanes();ByteBuffer yBuffer image.getPlanes()[0].getBuffer();
int ySize yBuffer.remaining();ByteBuffer vBuffer image.getPlanes()[2].getBuffer();
int vSize vBuffer.remaining();byte[] nv21_s new byte[WIDTH*HEIGHT * 3 / 2];try {yBuffer.get(nv21_s, 0, yBuffer.remaining());vBuffer.get(nv21_s, ySize, vBuffer.remaining());imageQueue.put(nv21_s);
} catch (Exception e) {throw new RuntimeException(e);
}image.close();
注
1.这种方式会缺最后一个像素的U分量或V分量如果追求完美对NV21可以从plane[1]中取出最后的值追加到末尾对NV12则是在plane[2]中取出最后的值追加到末尾
2.只适用于图像宽度为8的整数倍的情况否则因为需要做内存对齐后面会补0,导致image.getWidth() plane.getRowStride()这就需要对每一行舍去后面多余的0然后再拼接效率会低很多。