3

我有两个图像饱和度过滤器的实现。一种使用 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 内核。

4

1 回答 1

9

我立即可以看到您的 Renderscript 代码正在使用 rsDebug() 打印到日志中,这保证会很慢。尝试删除您的日志记录代码并再次测量时间。在这种情况下,Nexus 4 应该在 4 个 CPU 线程上执行。Nexus 4 目前不支持 GPU。

于 2013-03-16T22:18:51.937 回答