Подтвердить что ты не робот

Android ScriptIntrinsicBlur не размывает все изображение и генерирует прозрачный Edge

У меня есть некоторые проблемы с RenderScript ScriptIntrinsic Blur - на некоторых устройствах он не размывает весь образ. Я уменьшаю входное изображение и слежу за тем, чтобы ширина была кратной 4 (потому что это предложил Роман Нурик: 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 before blurringNexus 4 after blurring

Но на Галактике S4 правая сторона имеет прозрачный край:

Galaxy S4 before blurringGalaxy S4 after blurring

Надеюсь, вы поймете, что я имею в виду - если вы откроете картинку в gimp или вы увидите ее лучше. Это не зависит от размера изображения. Я также попробовал его с большими и меньшими изображениями, и результат всегда был одинаковым. Это также происходит на Nexus 7 2012, например. Кроме того, прозрачные артефакты иногда находятся на нижнем или левом краю. Заранее благодарим за помощь!

Nexus 4: 4.4.2/Номер сборки KOT49H Galaxy S4: 4.2.2/номер сборки JDQ39.I9505XXUDMGG

4b9b3361

Ответ 1

Я не уверен, почему это может сработать, но для меня это было сделано.

Попробуйте вместо

    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);

Ответ 2

Я предполагаю, что вы используете android.renderscript вместо поддержки lib android.v8.rderscript. (или старой поддержки lib?)

Если это правда, то это известная ошибка, которая может быть исправлена ​​только при обновлении системы, что может быть нецелесообразно для пользователей.

Один из способов решения этой проблемы - использовать библиотеку поддержки RenderScript: здесь вы можете найти подробные инструкции: 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

    }
}

Есть несколько преимуществ использования поддержки lib:

  • Поддержка устройств обратно в API 8.
  • Может быть обновлено с помощью Build-Tools, чтобы включить исправления ошибок и обходные пути.

С другой стороны, для достижения этой цели ему необходимо объединить несколько разделяемых библиотек, которые сделают ваше приложение более сильным.

Ответ 3

Мне все еще приходилось работать над тем, чтобы снять эту прозрачность, поэтому я закончил просто обрезать изображение на 25 пикселей после того, как я размыл его. Определенно не идеально, но он работал достаточно хорошо для моего применения ScriptIntrinsicBlur:

output = Bitmap.createBitmap(nbm, 25, 25, bm.getWidth() - 25, bm.getHeight() - 25);

Ответ 4

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;
}

}

;)