13

我对 RenderScript ScriptIntrinsic Blur 有一些问题 - 在某些设备上它不会模糊整个图像。我缩小输入图像并确保宽度是 4 的倍数(因为 Roman Nurik 建议:https: //plus.google.com/+RomanNurik/posts/TLkVQC3M6jW

@SuppressLint("NewApi")
private Bitmap blurRenderScript(Bitmap smallBitmap) {

    Bitmap output = Bitmap.createBitmap(smallBitmap.getWidth(), smallBitmap.getHeight(), smallBitmap.getConfig());

    RenderScript rs = RenderScript.create(getContext());
    ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
    Allocation inAlloc = Allocation.createFromBitmap(rs, smallBitmap, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_GRAPHICS_TEXTURE);
    Allocation outAlloc = Allocation.createFromBitmap(rs, output);
    script.setRadius(BLUR_RADIUS);
    script.setInput(inAlloc);
    script.forEach(outAlloc);
    outAlloc.copyTo(output);

    rs.destroy();

    MutableBitmap.delete(smallBitmap);

    return output;
}

它正在使用 Nexus 4:

模糊前的 Nexus 4模糊后的 Nexus 4

但在 Galaxy S4 上,右侧有一个透明边缘:

模糊前的 Galaxy S4模糊后的 Galaxy S4

我希望你能明白我的意思——如果你在 gimp 中打开图片或者你可以更好地看到它。它与图片大小无关。我还尝试了更大和更小的图像,结果总是一样的。例如,它也发生在 Nexus 7 2012 上。此外,透明伪影有时位于底部或左侧边缘。在此先感谢您的帮助!

Nexus 4:4.4.2/内部版本号 KOT49H Galaxy S4:4.2.2/内部版本号 JDQ39.I9505XXUDMGG

4

4 回答 4

3

我不确定为什么这可能有效,但对我来说确实有效..

尝试代替

    Bitmap output = Bitmap.createBitmap(smallBitmap.getWidth(), smallBitmap.getHeight(), smallBitmap.getConfig());

像这样传入 Bitmap.Config.ARGB_8888

    Bitmap output = Bitmap.createBitmap(smallBitmap.getWidth(), smallBitmap.getHeight(), Bitmap.Config.ARGB_8888);
于 2014-03-21T16:29:29.637 回答
2

我假设您使用的是 android.renderscript 而不是支持库 android.v8.renderscript。(或旧的支持库?)

如果是这样,那么这是一个已知的错误,只能通过系统升级来修复,这对用户来说可能不可行。

解决此问题的一种方法是使用 RenderScript Support lib:您可以在此处找到详细说明:http: //developer.android.com/guide/topics/renderscript/compute.html#access-rs-apis

基本上你只需要更改导入:

import android.support.v8.renderscript.*;

并配置你的 build.gradle:

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 19

        renderscriptTargetApi 18
        renderscriptSupportModeEnabled true

    }
}

使用支持库有几个优点:

  1. 支持设备回到 API 8。
  2. 可以使用 Build-Tools 进行更新,以合并错误修复和解决方法。

不利的一面是,要实现这一点,它需要捆绑几个共享库,这将使您的应用程序更强大。

于 2016-05-13T18:23:13.100 回答
1

我仍然无法采取任何措施来消除这种透明度,所以我在模糊后将图像修剪了 25 像素。绝对不理想,但它对我的 ScriptIntrinsicBlur 应用来说效果很好:

output = Bitmap.createBitmap(nbm, 25, 25, bm.getWidth() - 25, bm.getHeight() - 25);
于 2015-03-07T02:41:50.843 回答
-3

H!这适用于所有需要增加 ScriptIntrinsicBlur 的半径以获得更硬的高斯模糊的人。

您可以缩小图像并获得相同的结果,而不是将半径设置为超过 25。我写了一个名为 GaussianBlur 的类。下面你可以看到如何使用,以及整个类的实现。

用法:

    GaussianBlur gaussian = new GaussianBlur(context);
    gaussian.setMaxImageSize(60);
    gaussian.setRadius(25); //max

    Bitmap output = gaussian.render(<your bitmap>,true);
    Drawable d = new BitmapDrawable(getResources(),output);

班级:

public class GaussianBlur {
private final int DEFAULT_RADIUS = 25;
private final float DEFAULT_MAX_IMAGE_SIZE = 400;

private Context context;
private int radius;
private float maxImageSize;

public GaussianBlur(Context context) {
    this.context = context;
    setRadius(DEFAULT_RADIUS);
    setMaxImageSize(DEFAULT_MAX_IMAGE_SIZE);
}

public Bitmap render(Bitmap bitmap, boolean scaleDown) {
    RenderScript rs = RenderScript.create(context);

    if (scaleDown) {
        bitmap = scaleDown(bitmap);
    }

    Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);

    Allocation inAlloc = Allocation.createFromBitmap(rs, bitmap, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_GRAPHICS_TEXTURE);
    Allocation outAlloc = Allocation.createFromBitmap(rs, output);

    ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, inAlloc.getElement()); // Element.U8_4(rs));
    script.setRadius(getRadius());
    script.setInput(inAlloc);
    script.forEach(outAlloc);
    outAlloc.copyTo(output);

    rs.destroy();

    return output;
}

public Bitmap scaleDown(Bitmap input) {
    float ratio = Math.min((float) getMaxImageSize() / input.getWidth(), (float) getMaxImageSize() / input.getHeight());
    int width = Math.round((float) ratio * input.getWidth());
    int height = Math.round((float) ratio * input.getHeight());

    return Bitmap.createScaledBitmap(input, width, height, true);
}

public int getRadius() {
    return radius;
}

public void setRadius(int radius) {
    this.radius = radius;
}

public float getMaxImageSize() {
    return maxImageSize;
}

public void setMaxImageSize(float maxImageSize) {
    this.maxImageSize = maxImageSize;
}

}

;)

于 2014-10-17T13:52:50.893 回答