gpt4 book ai didi

android - 将 android.media.Image (YUV_420_888) 转换为位图

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:42:28 26 4
gpt4 key购买 nike

我正在尝试使用此处建议的 camera2 api 实现相机预览图像数据处理:Camera preview image data processing with Android L and Camera2 API .

我使用 onImageAvailableListener 成功接收到回调,但为了将来的处理,我需要从 YUV_420_888 android.media.Image 获取位图。我搜索了类似的问题,但都没有帮助。

能否建议我如何将 android.media.Image (YUV_420_888) 转换为位图,或者是否有更好的监听预览帧的方法?

最佳答案

您可以使用内置的 Renderscript intrinsic ScriptIntrinsicYuvToRGB 来做到这一点.代码取自 Camera2 api Imageformat.yuv_420_888 results on rotated image :

@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;
}

关于android - 将 android.media.Image (YUV_420_888) 转换为位图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28430024/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com