mol*_*mol 13 android bitmap yuv android-camera
我正在尝试使用这里提出的camera2 api实现相机预览图像数据处理:使用Android L和Camera2 API进行相机预览图像数据处理.
我使用onImageAvailableListener成功接收回调,但是为了将来的处理,我需要从YUV_420_888 android.media.Image获取位图.我搜索了类似的问题,但没有一个帮助.
你能否建议我如何将android.media.Image(YUV_420_888)转换为Bitmap,或者有更好的方法来监听预览帧?
您可以使用内置的 Renderscript 内在函数ScriptIntrinsicYuvToRGB. 从Camera2 api Imageformat.yuv_420_888获取的代码导致旋转图像:
Run Code Online (Sandbox Code Playgroud)@Override public void onImageAvailable(ImageReader reader) { // Get the YUV data final Image image = reader.acquireLatestImage(); final ByteBuffer yuvBytes = this.imageToByteBuffer(image); // Convert YUV to RGB final RenderScript rs = RenderScript.create(this.mContext); final Bitmap bitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888); final Allocation allocationRgb = Allocation.createFromBitmap(rs, bitmap); final Allocation allocationYuv = Allocation.createSized(rs, Element.U8(rs), yuvBytes.array().length); allocationYuv.copyFrom(yuvBytes.array()); ScriptIntrinsicYuvToRGB scriptYuvToRgb = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs)); scriptYuvToRgb.setInput(allocationYuv); scriptYuvToRgb.forEach(allocationRgb); allocationRgb.copyTo(bitmap); // Release bitmap.recycle(); allocationYuv.destroy(); allocationRgb.destroy(); rs.destroy(); image.close(); } private ByteBuffer imageToByteBuffer(final Image image) { final Rect crop = image.getCropRect(); final int width = crop.width(); final int height = crop.height(); final Image.Plane[] planes = image.getPlanes(); final byte[] rowData = new byte[planes[0].getRowStride()]; final int bufferSize = width * height * ImageFormat.getBitsPerPixel(ImageFormat.YUV_420_888) / 8; final ByteBuffer output = ByteBuffer.allocateDirect(bufferSize); int channelOffset = 0; int outputStride = 0; for (int planeIndex = 0; planeIndex < 3; planeIndex++) { if (planeIndex == 0) { channelOffset = 0; outputStride = 1; } else if (planeIndex == 1) { channelOffset = width * height + 1; outputStride = 2; } else if (planeIndex == 2) { channelOffset = width * height; outputStride = 2; } final ByteBuffer buffer = planes[planeIndex].getBuffer(); final int rowStride = planes[planeIndex].getRowStride(); final int pixelStride = planes[planeIndex].getPixelStride(); final int shift = (planeIndex == 0) ? 0 : 1; final int widthShifted = width >> shift; final int heightShifted = height >> shift; buffer.position(rowStride * (crop.top >> shift) + pixelStride * (crop.left >> shift)); for (int row = 0; row < heightShifted; row++) { final int length; if (pixelStride == 1 && outputStride == 1) { length = widthShifted; buffer.get(output.array(), channelOffset, length); channelOffset += length; } else { length = (widthShifted - 1) * pixelStride + 1; buffer.get(rowData, 0, length); for (int col = 0; col < widthShifted; col++) { output.array()[channelOffset] = rowData[col * pixelStride]; channelOffset += outputStride; } } if (row < heightShifted - 1) { buffer.position(buffer.position() + rowStride - length); } } } return output; }
有关更简单的解决方案,请参见此处的实现:
该函数以media.image作为输入,并基于y,u和v平面创建三个RenderScript分配。它遵循Wikipedia插图中所示的YUV_420_888逻辑。
但是,这里我们为Y,U和V通道提供了三个单独的图像平面,因此我将它们视为三个字节[],即U8分配。y分配的大小为宽度*高度字节,而u和v分配的大小为宽度*高度/ 4字节,这反映了每个u字节覆盖4个像素(与每个v字节同等)的事实。
小智 5
我写了一些关于这个的代码,它是 YUV 数据预览并将其更改为 JPEG 数据,我可以使用它来保存为位图、字节 [] 或其他。(您可以看到类“分配”)。
并且 SDK 文档说:
“为了使用 android.renderscript 进行高效的 YUV 处理:使用受支持的 YUV 类型、IO_INPUT 标志和 getOutputSizes(Allocation.class) 返回的大小之一创建 RenderScript Allocation,然后使用 getSurface( )”
这是代码,希望对你有帮助:https : //github.com/pinguo-yuyidong/Camera2/blob/master/camera2/src/main/rs/yuv2rgb.rs
| 归档时间: |
|
| 查看次数: |
13083 次 |
| 最近记录: |