我有两个图像饱和度过滤器的实现。一种使用 Java,另一种使用 Renderscript。实际上我的nexus 4设备上的renderscript比较慢,怎么可能?
Java实现:
public final void Saturation(Bitmap canvas, int saturation, boolean accumulate, int imageNumber)
{
int height = canvas.getHeight();
int width = canvas.getWidth();
int[] pixels = new int[height*width];
int[] resultPixels = new int[height*width];
canvas.getPixels(pixels, 0, width, 0, 0, width, height);
if (!accumulate)
{
for (int i = 0; i < pixels.length; i ++)
{
int red = Color.red(pixels[i]);
int green = Color.green(pixels[i]);
int blue = Color.blue(pixels[i]);
double t = (double)red * 0.11 + (double)green * 0.59 + (double)blue * 0.3;
red = (int)Math.round(Math.min((double)red + (t - (double)red) * saturation / 100.0, 255));
green = (int)Math.round(Math.min((double)green + (t - (double)green) * saturation / 100.0, 255));
blue = (int)Math.round(Math.min((double)blue + (t - (double)blue) * saturation / 100.0, 255));
resultPixels[i] = Color.argb(Color.alpha(pixels[i]), red, green, blue);
}
}
canvas.setPixels(resultPixels, 0, width, 0, 0, width, height);
}
渲染脚本实现:
Java部分:
public static Bitmap saturate(Bitmap bmIn, float saturation, Context context, Resources resources)
{
Bitmap bmOut = Bitmap.createBitmap(bmIn.getWidth(), bmIn.getHeight(),
bmIn.getConfig());
RenderScript rs = RenderScript.create(context);
Allocation allocIn;
allocIn = Allocation.createFromBitmap(rs, bmIn,
Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT);
Allocation allocOut = Allocation.createTyped(rs, allocIn.getType());
ScriptC_saturation script = new ScriptC_saturation(rs, resources,
R.raw.saturation);
script.set_in(allocIn);
script.set_out(allocOut);
script.set_script(script);
script.set_saturation(saturation);
script.invoke_filter();
allocOut.copyTo(bmOut);
return bmOut;
}
渲染脚本:
#pragma version(1)
#pragma rs java_package_name(ca.tutortutor.embossimage)
rs_allocation out;
rs_allocation in;
rs_script script;
float saturation;
void root(const uchar4* v_in, uchar4* v_out, const void* usrData, uint32_t x,
uint32_t y)
{
float4 current = rsUnpackColor8888(*v_in);
float t = current.r * 0.11f + current.g * 0.59f + current.b * 0.3f;
rsDebug("renderscript t = ", t);
rsDebug("renderscript red before = ", current.r);
current.r = fmin(current.r + (t - current.r) * saturation / 100.0f, 1.f);
current.g = fmin(current.g + (t - current.g) * saturation / 100.0f, 1.f);
current.b = fmin(current.b + (t - current.b) * saturation / 100.0f, 1.f);
rsDebug("renderscript red after = ", current.r);
*v_out = rsPackColorTo8888(current.r, current.g, current.b, current.a);
}
void filter()
{
rsDebug("RS_VERSION = ", RS_VERSION);
#if !defined(RS_VERSION) || (RS_VERSION < 14)
rsForEach(script, in, out, 0);
#else
rsForEach(script, in, out);
#endif
}
我认为 renderscript 应该比 java 快得多,因为它应该使用 cpu 和本机代码的所有 4 个内核,甚至可能是 android 4.2.2 上的 gpu 内核。