简体   繁体   English

尝试在Android手机上使用RenderScript支持库模糊图像时出错

[英]Error when trying to blur image using RenderScript support library on android phone

I'm trying to blur my image, and display it blurred on an RelativeLayout's background with RenderScript, the app works in the emulator but my app in the phone keeps crashing with this error: 我正在尝试模糊我的图像,并使用RenderScript在RelativeLayout的背景上显示模糊的图像,该应用程序可在模拟器中运行,但我手机中的应用程序始终因以下错误而崩溃:

08-05 22:21:36.543: E/RenderScript_jni(11549): No GC methods 08-05 22:21:36.553: D/dalvikvm(11549): No JNI_OnLoad found in /system/lib/libRSSupport.so 0x41803ab8, skipping init 08-05 22:21:36.557: E/dalvikvm(11549): ERROR: couldn't find native method 08-05 22:21:36.557: E/dalvikvm(11549): Requested: Landroid/support/v8/renderscript/RenderScript;._nInit:()V 08-05 22:21:36.558: E/JNIHelp(11549): RegisterNatives failed for 'android/support/v8/renderscript/RenderScript', aborting 08-05 22:21:36.558: A/libc(11549): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 11549 (m.example.login) 08-05 22:21:36.543:E / RenderScript_jni(11549):无GC方法08-05 22:21:36.553:D / dalvikvm(11549):在/system/lib/libRSSupport.so 0x41803ab8中找不到JNI_OnLoad,正在跳过初始化08-05 22:21:36.557:E / dalvikvm(11549):错误:找不到本机方法08-05 22:21:36.557:E / dalvikvm(11549):请求:Landroid / support / v8 / renderscript /RenderScript;._nInit:()V 08-05 22:21:36.558:E / JNIHelp(11549):RegisterNatives对于'android / support / v8 / renderscript / RenderScript'失败,中止08-05 22:21:36.558: A / libc(11549):致命信号11(SIGSEGV)位于0xdeadbaad(代码= 1),线程11549(m.example.login)

Here is my blur code on a seperate class: 这是我在一个单独的类上的模糊代码:

import android.content.Context;
import android.graphics.Bitmap;
import android.support.v8.renderscript.*;

public class Blur {
    public static Bitmap blurBitmap(Context context, Bitmap src) {
        Bitmap outBitmap = src.copy(src.getConfig(), true);

        final RenderScript rs = RenderScript.create(context);
        final Allocation input = Allocation.createFromBitmap(rs, src);
        final Allocation output = Allocation.createFromBitmap(rs, outBitmap);

        final ScriptIntrinsicBlur script =
                ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
        script.setRadius(25f);
        script.setInput(input);
        script.forEach(output);
        output.copyTo(outBitmap);

        rs.destroy();

        return outBitmap;
    }
}

and here is ny code in the MainActivity (I'm getting the Bitmap from the Gallery): 这是MainActivity中的ny代码(我从Gallery获得位图):

Uri selectedImageUri = data.getData();
Blur blur = new Blur();
imagepath = getRealPathFromURI(selectedImageUri);
Bitmap bmImg = BitmapFactory.decodeFile(imagepath);
Bitmap BlurredIMG = Blur.blurBitmap(getApplicationContext(), bmImg);
BitmapDrawable background = new BitmapDrawable(BlurredIMG);
rl.setBackgroundDrawable(background);

I had the same issue. 我遇到过同样的问题。 After hours of researching I've found another solution . 经过数小时的研究,我找到了另一种解决方案 It works very fast (around 10-15ms) if pre-scale image vertically and horizontally and then apply this algorithm. 如果在垂直和水平方向上预先缩放图像,然后应用此算法,它的工作速度非常快(大约10-15毫秒)
My solution looks like this 我的解决方案看起来像这样

//here we scale bitmap and apply blur
private Bitmap blur(Bitmap bkg) {

            float scaleFactor = 8;
            int radius = 2;
            int inputWidth = bkg.getWidth();
            int inputHeight = bkg.getHeight();

            Bitmap overlay = Bitmap.createBitmap((int)(inputWidth/scaleFactor),(int)(inputHeight/scaleFactor), Bitmap.Config.ARGB_8888);

            Canvas canvas = new Canvas(overlay);

            canvas.scale(1 / scaleFactor, 1 / scaleFactor);
            Paint paint = new Paint();
            paint.setFlags(Paint.FILTER_BITMAP_FLAG);

            canvas.drawBitmap(bkg, 0, 0, paint);

            //  bkg.recycle();
            overlay = FastBlur.doBlur(overlay, radius, true);
            return getResizedBitmap(overlay, inputWidth, inputHeight, true);

        }


        public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth, boolean willDelete) {

            int width = bm.getWidth();

            int height = bm.getHeight();

            float scaleWidth = ((float) newWidth) / width;

            float scaleHeight = ((float) newHeight) / height;

            // CREATE A MATRIX FOR THE MANIPULATION

            Matrix matrix = new Matrix();

            // RESIZE THE BIT MAP

            matrix.postScale(scaleWidth, scaleHeight);

            // RECREATE THE NEW BITMAP

            Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);

            //          if(willDelete)
            //              bm.recycle();

            return resizedBitmap;
        }

At last this is my class which wraps blur algorithm 最后这是我的课程,其中包含模糊算法

public class FastBlur {

    public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap) {

        // Stack Blur v1.0 from
        // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
        //
        // Java Author: Mario Klingemann <mario at quasimondo.com>
        // http://incubator.quasimondo.com
        // created Feburary 29, 2004
        // Android port : Yahel Bouaziz <yahel at kayenko.com>
        // http://www.kayenko.com
        // ported april 5th, 2012

        // This is a compromise between Gaussian Blur and Box blur
        // It creates much better looking blurs than Box Blur, but is
        // 7x faster than my Gaussian Blur implementation.
        //
        // I called it Stack Blur because this describes best how this
        // filter works internally: it creates a kind of moving stack
        // of colors whilst scanning through the image. Thereby it
        // just has to add one new block of color to the right side
        // of the stack and remove the leftmost color. The remaining
        // colors on the topmost layer of the stack are either added on
        // or reduced by one, depending on if they are on the right or
        // on the left side of the stack.
        //
        // If you are using this algorithm in your code please add
        // the following line:
        //
        // Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>

        Bitmap bitmap;
        if (canReuseInBitmap) {
            bitmap = sentBitmap;
        } else {
            bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
        }

        if (radius < 1) {
            return (null);
        }

        int w = bitmap.getWidth();
        int h = bitmap.getHeight();

        int[] pix = new int[w * h];
        bitmap.getPixels(pix, 0, w, 0, 0, w, h);

        int wm = w - 1;
        int hm = h - 1;
        int wh = w * h;
        int div = radius + radius + 1;

        int r[] = new int[wh];
        int g[] = new int[wh];
        int b[] = new int[wh];
        int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
        int vmin[] = new int[Math.max(w, h)];

        int divsum = (div + 1) >> 1;
        divsum *= divsum;
        int dv[] = new int[256 * divsum];
        for (i = 0; i < 256 * divsum; i++) {
            dv[i] = (i / divsum);
        }

        yw = yi = 0;

        int[][] stack = new int[div][3];
        int stackpointer;
        int stackstart;
        int[] sir;
        int rbs;
        int r1 = radius + 1;
        int routsum, goutsum, boutsum;
        int rinsum, ginsum, binsum;

        for (y = 0; y < h; y++) {
            rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
            for (i = -radius; i <= radius; i++) {
                p = pix[yi + Math.min(wm, Math.max(i, 0))];
                sir = stack[i + radius];
                sir[0] = (p & 0xff0000) >> 16;
                sir[1] = (p & 0x00ff00) >> 8;
                sir[2] = (p & 0x0000ff);
                rbs = r1 - Math.abs(i);
                rsum += sir[0] * rbs;
                gsum += sir[1] * rbs;
                bsum += sir[2] * rbs;
                if (i > 0) {
                    rinsum += sir[0];
                    ginsum += sir[1];
                    binsum += sir[2];
                } else {
                    routsum += sir[0];
                    goutsum += sir[1];
                    boutsum += sir[2];
                }
            }
            stackpointer = radius;

            for (x = 0; x < w; x++) {

                r[yi] = dv[rsum];
                g[yi] = dv[gsum];
                b[yi] = dv[bsum];

                rsum -= routsum;
                gsum -= goutsum;
                bsum -= boutsum;

                stackstart = stackpointer - radius + div;
                sir = stack[stackstart % div];

                routsum -= sir[0];
                goutsum -= sir[1];
                boutsum -= sir[2];

                if (y == 0) {
                    vmin[x] = Math.min(x + radius + 1, wm);
                }
                p = pix[yw + vmin[x]];

                sir[0] = (p & 0xff0000) >> 16;
                sir[1] = (p & 0x00ff00) >> 8;
                sir[2] = (p & 0x0000ff);

                rinsum += sir[0];
                ginsum += sir[1];
                binsum += sir[2];

                rsum += rinsum;
                gsum += ginsum;
                bsum += binsum;

                stackpointer = (stackpointer + 1) % div;
                sir = stack[(stackpointer) % div];

                routsum += sir[0];
                goutsum += sir[1];
                boutsum += sir[2];

                rinsum -= sir[0];
                ginsum -= sir[1];
                binsum -= sir[2];

                yi++;
            }
            yw += w;
        }
        for (x = 0; x < w; x++) {
            rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
            yp = -radius * w;
            for (i = -radius; i <= radius; i++) {
                yi = Math.max(0, yp) + x;

                sir = stack[i + radius];

                sir[0] = r[yi];
                sir[1] = g[yi];
                sir[2] = b[yi];

                rbs = r1 - Math.abs(i);

                rsum += r[yi] * rbs;
                gsum += g[yi] * rbs;
                bsum += b[yi] * rbs;

                if (i > 0) {
                    rinsum += sir[0];
                    ginsum += sir[1];
                    binsum += sir[2];
                } else {
                    routsum += sir[0];
                    goutsum += sir[1];
                    boutsum += sir[2];
                }

                if (i < hm) {
                    yp += w;
                }
            }
            yi = x;
            stackpointer = radius;
            for (y = 0; y < h; y++) {
                // Preserve alpha channel: ( 0xff000000 & pix[yi] )
                pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];

                rsum -= routsum;
                gsum -= goutsum;
                bsum -= boutsum;

                stackstart = stackpointer - radius + div;
                sir = stack[stackstart % div];

                routsum -= sir[0];
                goutsum -= sir[1];
                boutsum -= sir[2];

                if (x == 0) {
                    vmin[y] = Math.min(y + r1, hm) * w;
                }
                p = x + vmin[y];

                sir[0] = r[p];
                sir[1] = g[p];
                sir[2] = b[p];

                rinsum += sir[0];
                ginsum += sir[1];
                binsum += sir[2];

                rsum += rinsum;
                gsum += ginsum;
                bsum += binsum;

                stackpointer = (stackpointer + 1) % div;
                sir = stack[stackpointer];

                routsum += sir[0];
                goutsum += sir[1];
                boutsum += sir[2];

                rinsum -= sir[0];
                ginsum -= sir[1];
                binsum -= sir[2];

                yi += w;
            }
        }

        bitmap.setPixels(pix, 0, w, 0, 0, w, h);

        return (bitmap);
    }

}

With best regards 最诚挚的问候

Check your build.gradle file (Android Studio) or project.properties (Eclipse). 检查您的build.gradle文件(Android Studio)或project.properties(Eclipse)。 This sounds like you do not have it set to include RS support mode and targeted API level correctly. 听起来您没有将其设置为正确包含RS支持模式和目标API级别。 See the answer here: android can't load SupportV8 RenderScript in api <17 请在此处查看答案: android无法在api <17中加载SupportV8 RenderScript

This code work perfect for me. 这段代码对我来说很完美。

and setRadius between 0 to 23. 并将Radius设置为0到23之间。

like "blur.setRadius(21)" 就像“ blur.setRadius(21)”

Bitmap tempbg = BitmapFactory.decodeResource(getResources(),R.drawable.b1); //Load a  background.
Bitmap final_Bitmap = BlurImage(tempbg);

@SuppressLint("NewApi")
Bitmap BlurImage (Bitmap input)
{
    try
    {
    RenderScript  rsScript = RenderScript.create(getApplicationContext());
    Allocation alloc = Allocation.createFromBitmap(rsScript, input);

    ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(rsScript, Element.U8_4(rsScript));
    blur.setRadius(21);
    blur.setInput(alloc);

    Bitmap result = Bitmap.createBitmap(input.getWidth(), input.getHeight(), Bitmap.Config.ARGB_8888);
    Allocation outAlloc = Allocation.createFromBitmap(rsScript, result);

    blur.forEach(outAlloc);
    outAlloc.copyTo(result);

    rsScript.destroy();
    return result;
    }
    catch (Exception e) {
        // TODO: handle exception
        return input;
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM