从 Android 12 开始,RenderScript API 已被废弃。
1、RenderScript介绍
RenderScript 是用于在 Android 上以高性能运行计算密集型任务的框架。RenderScript 主要用于数据并行计算,不过串行工作负载也可以从中受益。RenderScript 运行时可在设备上提供的多个处理器(如多核 CPU 和 GPU)间并行调度工作。这样您就能够专注于表达算法而不是调度工作。RenderScript 对于执行图像处理、计算摄影或计算机视觉的应用来说尤其有用。
Android 12 中弃用 RenderScript API,Google 在 Android开发者博客中提到,其实早已不建议将RenderScript用于对性能需求至关重要的任务, Android开发者应该转向可在GPU硬件层级上高效运作、且具有出色的跨平台体验的Vulkan API 。并还提供了示例,对比RenderScript 和 Vulkan API 的运行差异。
google官方链接
2、NV21格式转Bitmap
使用RenderScript高效的将Camera回调的NV21格式转Bitmap
package com.my.camerademo;
import android.content.Context;
import android.graphics.Bitmap;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicYuvToRGB;
import android.renderscript.Type;
public class NV21ToBitmap {
private RenderScript rs;
private ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic;
private Type.Builder yuvType, rgbaType;
private Allocation in, out;
public NV21ToBitmap(Context context) {
rs = RenderScript.create(context);
yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
}
public Bitmap nv21ToBitmap(byte[] nv21, int width, int height){
if (yuvType == null){
yuvType = new Type.Builder(rs, Element.U8(rs)).setX(nv21.length);
in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);
rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height);
out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
}
in.copyFrom(nv21);
yuvToRgbIntrinsic.setInput(in);
yuvToRgbIntrinsic.forEach(out);
Bitmap bmpout = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
out.copyTo(bmpout);
return bmpout;
}
}
3、使用RenderScript实现图片高斯模糊效果
public class BlurBitmap {
private static final float BITMAP_SCALE = 1.0f;
private static final float BLUR_RADIUS = 25;
public static Bitmap blur(Context context, Bitmap image) {
int width = Math.round(image.getWidth() * BITMAP_SCALE);
int height = Math.round(image.getHeight() * BITMAP_SCALE);
Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
RenderScript rs = RenderScript.create(context);
ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
theIntrinsic.setRadius(BLUR_RADIUS);
theIntrinsic.setInput(tmpIn);
theIntrinsic.forEach(tmpOut);
tmpOut.copyTo(outputBitmap);
return outputBitmap;
}
}
4、使用RenderScript进行直方图均衡化(histEq.rs)
#pragma version(1)
#pragma rs_fp_relaxed
#pragma rs java_package_name(com.example.q.renderscriptexample)
#include "rs_debug.rsh"
int32_t histo[256];
float remapArray[256];
int size;
//Method to keep the result between 0 and 1
static float bound (float val) {
float m = fmax(0.0f, val);
return fmin(1.0f, m);
}
uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
//Convert input uchar4 to float4
float4 f4 = rsUnpackColor8888(in);
//Get YUV channels values
float Y = 0.299f * f4.r + 0.587f * f4.g + 0.114f * f4.b;
float U = ((0.492f * (f4.b - Y))+1)/2;
float V = ((0.877f * (f4.r - Y))+1)/2;
//Get Y value between 0 and 255 (included)
int32_t val = Y * 255;
//Increment histogram for that value
rsAtomicInc(&histo[val]);
//Put the values in the output uchar4, note that we keep the alpha value
return rsPackColorTo8888(Y, U, V, f4.a);
}
uchar4 __attribute__((kernel)) remaptoRGB(uchar4 in, uint32_t x, uint32_t y) {
//Convert input uchar4 to float4
float4 f4 = rsUnpackColor8888(in);
//Get Y value
float Y = f4.r;
//Get Y value between 0 and 255 (included)
int32_t val = Y * 255;
//Get Y new value in the map array
Y = remapArray[val];
//Get value for U and V channel (back to their original values)
float U = (2*f4.g)-1;
float V = (2*f4.b)-1;
//Compute values for red, green and blue channels
float red = bound(Y + 1.14f * V);
float green = bound(Y - 0.395f * U - 0.581f * V);
float blue = bound(Y + 2.033f * U);
//Put the values in the output uchar4
return rsPackColorTo8888(red, green, blue, f4.a);
}
void init() {
//init the array with zeros
for (int i = 0; i < 256; i++) {
histo[i] = 0;
remapArray[i] = 0.0f;
}
}
void createRemapArray() {
//create map for y
float sum = 0;
for (int i = 0; i < 256; i++) {
sum += histo[i];
remapArray[i] = sum / (size);
}
}
Java调用
public static Bitmap histogramEqualization(Bitmap image, Context context) {
//Get image size
int width = image.getWidth();
int height = image.getHeight();
//Create new bitmap
Bitmap res = image.copy(image.getConfig(), true);
//Create renderscript
RenderScript rs = RenderScript.create(context);
//Create allocation from Bitmap
Allocation allocationA = Allocation.createFromBitmap(rs, res);
//Create allocation with same type
Allocation allocationB = Allocation.createTyped(rs, allocationA.getType());
//Create script from rs file.
ScriptC_histEq histEqScript = new ScriptC_histEq(rs);
//Set size in script
histEqScript.set_size(width*height);
//Call the first kernel.
histEqScript.forEach_root(allocationA, allocationB);
//Call the rs method to compute the remap array
histEqScript.invoke_createRemapArray();
//Call the second kernel
histEqScript.forEach_remaptoRGB(allocationB, allocationA);
//Copy script result into bitmap
allocationA.copyTo(res);
//Destroy everything to free memory
allocationA.destroy();
allocationB.destroy();
histEqScript.destroy();
rs.destroy();
return res;
}