从 Android 12 开始,RenderScript API 已被弃用。
Google推荐使用更加高效的Vulkan。
不过这篇文件还是介绍RenderScript 的使用,RenderScript 相对比较简单一些。
RenderScript 是用于在 Android 上以高性能运行计算密集型任务的框架。
RenderScript 专为数据并行计算而设计,不过串行工作负载也可以从中受益。
RenderScript 运行时可以并行安排设备上可用的多个处理器(如多核 CPU 和 GPU)上的工作负载,使开发者能够专注于表达算法而不是调度工作。RenderScript 对于专注于图像处理、计算摄影或计算机视觉的应用来说尤其有用。
关于RenderScript ,Google的官方介绍文档。
https://source.android.google.cn/docs/core/architecture/vndk/renderscript?hl=zh-cn
RenderScript 使用示例:
下面示例内容是,在imageReader的回调里面,实时的将yuv420_888转为bitmap。
mYuvImageReader = ImageReader.newInstance(1920, 1080,
ImageFormat.YUV_420_888, 4);
private final ImageReader.OnImageAvailableListener mOnYuvImageAvailableListener
= new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireLatestImage();
if (image != null) {
Log.e(TAG,"YUV_420_888_toRGBIntrinsics start");
mBitMap = YUV_420_888_toRGBIntrinsics(image,getActivity());
mHandler.post(new Runnable() {
@Override
public void run() {
showImage(mBitMap);
}
});
Log.e(TAG,"YUV_420_888_toRGBIntrinsics end");
}
}
};
private static RenderScript rs;
private static Bitmap YUV_420_888_toRGBIntrinsics(Image image,Context context) {
if (image == null) return null;
int W = image.getWidth();
int H = image.getHeight();
Image.Plane Y = image.getPlanes()[0];
Image.Plane U = image.getPlanes()[1];
Image.Plane V = image.getPlanes()[2];
int Yb = Y.getBuffer().remaining();
int Ub = U.getBuffer().remaining();
int Vb = V.getBuffer().remaining();
byte[] data = new byte[Yb + Ub + Vb];
Y.getBuffer().get(data, 0, Yb);
V.getBuffer().get(data, Yb, Vb);
U.getBuffer().get(data, Yb + Vb, Ub);
rs = RenderScript.create(context);
ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs)).setX(data.length);
Allocation in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);
Type.Builder rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(W).setY(H);
Allocation out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
final Bitmap bmpout = Bitmap.createBitmap(W, H, Bitmap.Config.ARGB_8888);
in.copyFromUnchecked(data);
yuvToRgbIntrinsic.setInput(in);
yuvToRgbIntrinsic.forEach(out);
out.copyTo(bmpout);
image.close();
return bmpout ;
}
日志打印:从下面日志可以看到,1920 * 1080的分辨率下,转换耗时在30 ms左右。
2023-12-25 14:06:27.294 15912-22157 Camera2BasicFragment com.android.camera2demo E YUV_420_888_toRGBIntrinsics end
2023-12-25 14:06:27.311 15912-22157 Camera2BasicFragment com.android.camera2demo E YUV_420_888_toRGBIntrinsics start
2023-12-25 14:06:27.352 15912-22157 Camera2BasicFragment com.android.camera2demo E YUV_420_888_toRGBIntrinsics end
2023-12-25 14:06:27.353 15912-22157 Camera2BasicFragment com.android.camera2demo E YUV_420_888_toRGBIntrinsics start
2023-12-25 14:06:27.371 15912-22157 Camera2BasicFragment com.android.camera2demo E YUV_420_888_toRGBIntrinsics end
2023-12-25 14:06:27.398 15912-22157 Camera2BasicFragment com.android.camera2demo E YUV_420_888_toRGBIntrinsics start
2023-12-25 14:06:27.415 15912-22157 Camera2BasicFragment com.android.camera2demo E YUV_420_888_toRGBIntrinsics end
2023-12-25 14:06:27.435 15912-22157 Camera2BasicFragment com.android.camera2demo E YUV_420_888_toRGBIntrinsics start
扩展:
1、Vulkan
Vulkan在Android使用Compute shader
https://zhuanlan.zhihu.com/p/258130830 https://blog.51cto.com/u_16099335/6861390
2、libyuv
https://github.com/GitLqr/LQRLibyuv