programing

Android SDK용 고속 비트맵 흐림

kingscode 2022. 8. 25. 22:04
반응형

Android SDK용 고속 비트맵 흐림

현재 개발 중인 Android 어플리케이션에서는 이미지를 흐리게 하기 위해 픽셀을 반복하고 있습니다.640 x 480 이미지에서는 이 작업은 약 30초 걸립니다.

Android Market에서 앱을 브라우징하던 중 흐림 기능Android SDK용 고속 비트맵 흐림이 포함된 앱을 발견했는데, 흐림 속도가 매우 빠르기 때문에(5초 정도) 다른 방법을 사용하고 있을 것입니다.

픽셀을 반복하는 것 말고 더 빠른 방법을 아는 사람?

미래의 구글을 위해 Quasimondo에서 포팅한 알고리즘을 소개합니다.박스 블러와 가우스 블러 사이의 혼합입니다. 매우 예쁘고 속도도 빠릅니다.

코멘트 내의 ArrayIndexOutOfBoundsException 문제: @anthonycr이 발생한 사용자의 업데이트는 다음 정보를 제공합니다.

Math.abs를 StrictMath.abs 또는 다른 복근 구현으로 대체하면 크래시가 발생하지 않는다는 것을 알게 되었습니다.

/**
 * 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>
 */

public Bitmap fastblur(Bitmap sentBitmap, float scale, int radius) {

    int width = Math.round(sentBitmap.getWidth() * scale);
    int height = Math.round(sentBitmap.getHeight() * scale);
    sentBitmap = Bitmap.createScaledBitmap(sentBitmap, width, height, false);

    Bitmap 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];
    Log.e("pix", w + " " + h + " " + pix.length);
    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;
        }
    }

    Log.e("pix", w + " " + h + " " + pix.length);
    bitmap.setPixels(pix, 0, w, 0, 0, w, h);

    return (bitmap);
}

Android Blur 가이드 2016

Showcase/Benchmark 앱과 소스를 Github에서 제공합니다.또한 현재 작업 중인 Blur 프레임워크도 확인하십시오. Dali.

많은 실험을 한 후 Android Framework를 사용할 때 Android에서 더 쉽게 사용할 수 있는 확실한 권장 사항을 알려드리겠습니다.

다운스케일 비트맵 로드 및 사용(매우 흐릿한 이미지의 경우)

비트맵의 전체 크기를 사용하지 마십시오.이미지가 클수록 더 많은 것을 흐리게 할 필요가 있습니다.또한 흐림 반경이 커야 합니다.보통 흐림 반경이 클수록 알고리즘의 시간이 길어집니다.

final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap blurTemplate = BitmapFactory.decodeResource(getResources(), R.drawable.myImage, options);

에 러러비 this this가 로드됩니다.inSampleSize8면 64면 1면 1이다. 대상inSampleSize니즈에 적합하지만 스케일링으로 인한 품질 저하를 방지하기 위해 2^n(2,4,8,...)으로 유지합니다.자세한 내용은 Google 문서를 참조하십시오.

또 다른 큰 장점은 비트맵 로딩 속도가 매우 빠르다는 것입니다.초기 흐림 테스트에서는 전체 흐림 프로세스에서 가장 긴 시간이 이미지 로딩이라고 생각했습니다.디스크에서 1920x1080 이미지를 로드하려면 Nexus 5는 500ms가 필요했지만 흐릿한 부분은 250ms 정도밖에 걸리지 않았습니다.

렌더링 스크립트 사용

렌더링 스크립트는 어떤 것이 가우스 블러 필터인지 제공합니다.시각적으로도 좋고, Android에서 현실적으로 가장 빠른 속도입니다.구글은 "일반적으로 멀티스레드 C 구현보다 2~3배 빠르며 종종 자바 구현보다 10배 이상 빠르다"고 주장한다.렌더링 스크립트는 매우 정교하며(가장 빠른 처리 장치(GPU, ISP 등) 2.2까지 호환되는 v8 지원 라이브러리도 있습니다.적어도 이론상으로는 다른 개발자의 테스트나 보고서를 통해서는 Renderscript를 무작정 사용할 수 없는 것 같습니다.하드웨어/드라이버 플래그멘테이션으로 인해 일부 디바이스에서는 문제가 발생할 수 있기 때문입니다(예를 들어 4.1 Nexus S에서 문제가 발생했습니다).여러 디바이스에서 주의해서 테스트해 주세요.다음은 시작할 수 있는 간단한 예입니다.

//define this only once if blurring multiple times
RenderScript rs = RenderScript.create(context);

(...)
//this will blur the bitmapOriginal with a radius of 8 and save it in bitmapOriginal
final Allocation input = Allocation.createFromBitmap(rs, bitmapOriginal); //use this constructor for best performance, because it uses USAGE_SHARED mode which reuses memory
final Allocation output = Allocation.createTyped(rs, input.getType());
final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
script.setRadius(8f);
script.setInput(input);
script.forEach(output);
output.copyTo(bitmapOriginal);

구글이 특별히 권장하는 Gradle과 함께 v8 지원을 사용할 경우 빌드 스크립트에 두 줄만 추가하면 됩니다.android.support.v8.renderscript현재 빌드 도구 사용(Android Gradle 플러그인 v14+의 업데이트된 구문)

android {
    ...
    defaultConfig {
        ...
        renderscriptTargetApi 19
        renderscriptSupportModeEnabled true
    }
}

Nexus 5의 간단한 벤치마크 - RenderScript를 다른 자바 및 Renderscript 구현과 비교:

다양한 사진 크기에서의 흐림당 평균 실행 시간한 사진

흐릿해질 수 있는 메가픽셀/초초( sec)로 수 .

250달러 RS_GAUSS_FASTScriptIntrinsicBlur 거의 빠릅니다), (가장 빠릅니다), ( 빠릅니다), (가장 빠릅니다), ( 빠릅니다)로 시작하는 것.RS_는 대부분 단순한 커널을 사용한 복잡한 구현입니다.알고리즘에 대한 자세한 내용은 여기를 참조하십시오.측정되는 가비지 수집이 좋은 부분이기 때문에 이것은 단순히 흐릿한 것이 아닙니다.이것은 여기서 확인할 수 있습니다(ScriptIntrinsicBlur상)500100 500100 on 500100 。

여기에 이미지 설명 입력

스파이크는 gc입니다.

벤치마크 앱은 플레이스토어에 있습니다: BlurBenchmark

가능한 한 비트맵 재사용 (prio: 퍼포먼스> 메모리 용량)

라이브 블러 등에 여러 개의 블러가 필요하고 메모리로 인해 드로더블에서 비트맵이 여러 번 로드되지 않고 멤버 변수에 "캐시"된 상태로 유지됩니다.이 경우 가비지 수집을 최소한으로 유지하기 위해 항상 동일한 변수를 사용합니다.

또한 파일 또는 그리기 가능 파일에서 로드하는 경우 비트맵 메모리를 재사용하여 가비지 수집 시간을 절약할 수 있는 새 옵션을 선택하십시오.

선명한 것부터 흐릿한 것까지 블렌딩에 사용

2면 .ImageViews하나는 흐리고, 알파는 희미해집니다.하지만 선명함에서 흐릿함까지 매끄럽게 퇴색하고 싶다면 Roman Nurik의 Muzei 앱처럼 하는 방법을 게시물을 확인해 보세요.

기본적으로 그는 흐릿한 익스텐트가 다른 프레임을 미리 블러하여 매우 부드럽게 보이는 애니메이션의 키 프레임으로 사용한다고 설명합니다.

Nurik이 자신의 접근 방식을 확장한 도표

이것은 어두운 장면이지만 이미지를 축소했다가 다시 확대해 볼 수 있습니다. 하면 .Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter).true로 사실네이티브 코드로 실행되므로 더 빠를 수 있습니다.

편집 (2014년 4월):이 문답 페이지는 여전히 많은 조회수를 기록하고 있는 것 같습니다.나는 내가 항상 이 직책을 위해 표를 얻고 있다는 것을 안다.하지만 이 글을 읽고 있다면, 여기에 게시된 답변( 답변과 승인된 답변 모두)이 최신이 아님을 깨달아야 합니다.현재 효율적인 블러를 구현하려면 NDK 또는 Java 대신 RenderScript를 사용해야 합니다.RenderScript는 Android 2.2+(Android 지원 라이브러리 사용)에서 실행되므로 사용하지 않을 이유가 없습니다.

오래된 답이 뒤따르지만, 시대에 뒤떨어진 것이므로 주의하세요.


future² 구글러에 대해서는 Yahel의 Quasimondo 알고리즘 포트에서 NDK를 사용하여 포팅한 알고리즘을 소개합니다.물론 야헬의 대답에 기초하고 있습니다.하지만 이건 네이티브 C 코드를 실행하고 있기 때문에 더 빠릅니다.훨씬 더 빨라요.40배는 빨라요

NDK를 사용하는 것이 모든 이미지 조작을 Android에서 하는 방법이라는 것을 알았습니다.처음에는 다소 귀찮지만(여기서 JNI와 NDK 사용에 대한 훌륭한 튜토리얼을 읽는다), 훨씬 낫고 많은 부분에서 거의 실시간에 가깝다.

참고로 Yahel의 Java 기능을 사용하여 480x532픽셀의 이미지를 흐리게 하는 데 10초가 걸렸습니다.하지만 네이티브 C 버전을 사용하면 250ms가 걸렸습니다.그리고 더 최적화될 수 있을 거라고 확신해요자바 코드를 바보같이 변환했습니다. 아마 단축할 수 있는 조작이 있을 겁니다. 전체 리팩터에 너무 많은 시간을 할애하고 싶지 않았습니다.

#include <jni.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <android/log.h>
#include <android/bitmap.h>

#define LOG_TAG "libbitmaputils"
#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

typedef struct {
    uint8_t red;
    uint8_t green;
    uint8_t blue;
    uint8_t alpha;
} rgba;

JNIEXPORT void JNICALL Java_com_insert_your_package_ClassName_functionToBlur(JNIEnv* env, jobject obj, jobject bitmapIn, jobject bitmapOut, jint radius) {
    LOGI("Blurring bitmap...");

    // Properties
    AndroidBitmapInfo   infoIn;
    void*               pixelsIn;
    AndroidBitmapInfo   infoOut;
    void*               pixelsOut;

    int ret;

    // Get image info
    if ((ret = AndroidBitmap_getInfo(env, bitmapIn, &infoIn)) < 0 || (ret = AndroidBitmap_getInfo(env, bitmapOut, &infoOut)) < 0) {
        LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
        return;
    }

    // Check image
    if (infoIn.format != ANDROID_BITMAP_FORMAT_RGBA_8888 || infoOut.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
        LOGE("Bitmap format is not RGBA_8888!");
        LOGE("==> %d %d", infoIn.format, infoOut.format);
        return;
    }

    // Lock all images
    if ((ret = AndroidBitmap_lockPixels(env, bitmapIn, &pixelsIn)) < 0 || (ret = AndroidBitmap_lockPixels(env, bitmapOut, &pixelsOut)) < 0) {
        LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    }

    int h = infoIn.height;
    int w = infoIn.width;

    LOGI("Image size is: %i %i", w, h);

    rgba* input = (rgba*) pixelsIn;
    rgba* output = (rgba*) pixelsOut;

    int wm = w - 1;
    int hm = h - 1;
    int wh = w * h;
    int whMax = max(w, h);
    int div = radius + radius + 1;

    int r[wh];
    int g[wh];
    int b[wh];
    int rsum, gsum, bsum, x, y, i, yp, yi, yw;
    rgba p;
    int vmin[whMax];

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

    yw = yi = 0;

    int stack[div][3];
    int stackpointer;
    int stackstart;
    int rbs;
    int ir;
    int ip;
    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 = input[yi + min(wm, max(i, 0))];

            ir = i + radius; // same as sir

            stack[ir][0] = p.red;
            stack[ir][1] = p.green;
            stack[ir][2] = p.blue;
            rbs = r1 - abs(i);
            rsum += stack[ir][0] * rbs;
            gsum += stack[ir][1] * rbs;
            bsum += stack[ir][2] * rbs;
            if (i > 0) {
                rinsum += stack[ir][0];
                ginsum += stack[ir][1];
                binsum += stack[ir][2];
            } else {
                routsum += stack[ir][0];
                goutsum += stack[ir][1];
                boutsum += stack[ir][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;
            ir = stackstart % div; // same as sir

            routsum -= stack[ir][0];
            goutsum -= stack[ir][1];
            boutsum -= stack[ir][2];

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

            stack[ir][0] = p.red;
            stack[ir][1] = p.green;
            stack[ir][2] = p.blue;

            rinsum += stack[ir][0];
            ginsum += stack[ir][1];
            binsum += stack[ir][2];

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

            stackpointer = (stackpointer + 1) % div;
            ir = (stackpointer) % div; // same as sir

            routsum += stack[ir][0];
            goutsum += stack[ir][1];
            boutsum += stack[ir][2];

            rinsum -= stack[ir][0];
            ginsum -= stack[ir][1];
            binsum -= stack[ir][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 = max(0, yp) + x;

            ir = i + radius; // same as sir

            stack[ir][0] = r[yi];
            stack[ir][1] = g[yi];
            stack[ir][2] = b[yi];

            rbs = r1 - abs(i);

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

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

            if (i < hm) {
                yp += w;
            }
        }
        yi = x;
        stackpointer = radius;
        for (y = 0; y < h; y++) {
            output[yi].red = dv[rsum];
            output[yi].green = dv[gsum];
            output[yi].blue = dv[bsum];

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

            stackstart = stackpointer - radius + div;
            ir = stackstart % div; // same as sir

            routsum -= stack[ir][0];
            goutsum -= stack[ir][1];
            boutsum -= stack[ir][2];

            if (x == 0) vmin[y] = min(y + r1, hm) * w;
            ip = x + vmin[y];

            stack[ir][0] = r[ip];
            stack[ir][1] = g[ip];
            stack[ir][2] = b[ip];

            rinsum += stack[ir][0];
            ginsum += stack[ir][1];
            binsum += stack[ir][2];

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

            stackpointer = (stackpointer + 1) % div;
            ir = stackpointer; // same as sir

            routsum += stack[ir][0];
            goutsum += stack[ir][1];
            boutsum += stack[ir][2];

            rinsum -= stack[ir][0];
            ginsum -= stack[ir][1];
            binsum -= stack[ir][2];

            yi += w;
        }
    }

    // Unlocks everything
    AndroidBitmap_unlockPixels(env, bitmapIn);
    AndroidBitmap_unlockPixels(env, bitmapOut);

    LOGI ("Bitmap blurred.");
}

int min(int a, int b) {
    return a > b ? b : a;
}

int max(int a, int b) {
    return a > b ? a : b;
}

그런 다음 다음과 같이 사용합니다(com.insert.your.package라는 클래스를 고려).ClassName 및 위의 코드와 같이 functionToBlur라는 네이티브 함수:

// Create a copy
Bitmap bitmapOut = bitmapIn.copy(Bitmap.Config.ARGB_8888, true);
// Blur the copy
functionToBlur(bitmapIn, bitmapOut, __radius);

RGB_8888 비트맵이 필요합니다!

비트맵을 를 전달하기 전에 변환된 복사를 RGB_565를 하도록 함수를 합니다.rgb565 타이핑하다rgba:

typedef struct {
    uint16_t byte0;
} rgb565;

는 그렇게 읽히지 예요..red,.green ★★★★★★★★★★★★★★★★★」.blue . 상 、 duh .이 、 of of of of of of of 。★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

r = (pixels[x].byte0 & 0xF800) >> 8;
g = (pixels[x].byte0 & 0x07E0) >> 3;
b = (pixels[x].byte0 & 0x001F) << 3;

하지만 아마 덜 멍청한 방법이 있을 거야.유감이지만, 난 C 코더는 별로야.

이 코드는 나에게 완벽한 기능이다.

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

}

RenderScript 라이브러리에서 ScriptIntrinsicBlur를 사용하여 빠르게 흐릿해질 수 있습니다.다음은 RenderScript API에 액세스하는 방법입니다.다음은 뷰와 비트맵을 흐리게 하기 위한 수업입니다.

public class BlurBuilder {
    private static final float BITMAP_SCALE = 0.4f;
    private static final float BLUR_RADIUS = 7.5f;

    public static Bitmap blur(View v) {
        return blur(v.getContext(), getScreenshot(v));
    }

    public static Bitmap blur(Context ctx, Bitmap image) {
        int width = Math.round(image.getWidth() * BITMAP_SCALE);
        int height = Math.round(image.getHeight() * BITMAP_SCALE);

        Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
        Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);

        RenderScript rs = RenderScript.create(ctx);
        ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
        Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
        Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
        theIntrinsic.setRadius(BLUR_RADIUS);
        theIntrinsic.setInput(tmpIn);
        theIntrinsic.forEach(tmpOut);
        tmpOut.copyTo(outputBitmap);

        return outputBitmap;
    }

    private static Bitmap getScreenshot(View v) {
        Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(b);
        v.draw(c);
        return b;
    }
}

이것은 나에게 잘 작동했다.Android의 RenderScript로 이미지를 효율적으로 흐리게 하는 방법

public class BlurBuilder {
    private static final float BITMAP_SCALE = 0.4f;
    private static final float BLUR_RADIUS = 7.5f;

    @SuppressLint("NewApi")
    public static Bitmap blur(Context context, Bitmap image) {
        int width = Math.round(image.getWidth() * BITMAP_SCALE);
        int height = Math.round(image.getHeight() * BITMAP_SCALE);

        Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height,
            false);
        Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);

        RenderScript rs = RenderScript.create(context);
        ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs,
            Element.U8_4(rs));
        Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
        Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
        theIntrinsic.setRadius(BLUR_RADIUS);
        theIntrinsic.setInput(tmpIn);
        theIntrinsic.forEach(tmpOut);
        tmpOut.copyTo(outputBitmap);

        return outputBitmap;
    }
}

@Yahel 코드 감사합니다.알파 채널에서 지원하는 기능이 불분명한 동일한 방법을 게시하면 다른 사용자의 시간을 절약할 수 있습니다.

/**
 * Stack Blur v1.0 from
 * http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
 * Java Author: Mario Klingemann <mario at quasimondo.com>
 * http://incubator.quasimondo.com
 * <p/>
 * created Feburary 29, 2004
 * Android port : Yahel Bouaziz <yahel at kayenko.com>
 * http://www.kayenko.com
 * ported april 5th, 2012
 * <p/>
 * 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.
 * <p/>
 * 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.
 * <p/>
 * If you are using this algorithm in your code please add
 * the following line:
 * Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
 */

public static Bitmap fastblur(Bitmap sentBitmap, float scale, int radius) {

    int width = Math.round(sentBitmap.getWidth() * scale);
    int height = Math.round(sentBitmap.getHeight() * scale);
    sentBitmap = Bitmap.createScaledBitmap(sentBitmap, width, height, false);

    Bitmap 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];
    Log.e("pix", w + " " + h + " " + pix.length);
    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 a[] = new int[wh];
    int rsum, gsum, bsum, asum, 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][4];
    int stackpointer;
    int stackstart;
    int[] sir;
    int rbs;
    int r1 = radius + 1;
    int routsum, goutsum, boutsum, aoutsum;
    int rinsum, ginsum, binsum, ainsum;

    for (y = 0; y < h; y++) {
        rinsum = ginsum = binsum = ainsum = routsum = goutsum = boutsum = aoutsum = rsum = gsum = bsum = asum = 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);
            sir[3] = 0xff & (p >> 24);

            rbs = r1 - Math.abs(i);
            rsum += sir[0] * rbs;
            gsum += sir[1] * rbs;
            bsum += sir[2] * rbs;
            asum += sir[3] * rbs;
            if (i > 0) {
                rinsum += sir[0];
                ginsum += sir[1];
                binsum += sir[2];
                ainsum += sir[3];
            } else {
                routsum += sir[0];
                goutsum += sir[1];
                boutsum += sir[2];
                aoutsum += sir[3];
            }
        }
        stackpointer = radius;

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

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

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

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

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

            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);
            sir[3] = 0xff & (p >> 24);

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

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

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

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

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

            yi++;
        }
        yw += w;
    }
    for (x = 0; x < w; x++) {
        rinsum = ginsum = binsum = ainsum = routsum = goutsum = boutsum = aoutsum = rsum = gsum = bsum = asum = 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];
            sir[3] = a[yi];

            rbs = r1 - Math.abs(i);

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

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

            if (i < hm) {
                yp += w;
            }
        }
        yi = x;
        stackpointer = radius;
        for (y = 0; y < h; y++) {
            pix[yi] = (dv[asum] << 24) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];

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

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

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

            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];
            sir[3] = a[p];

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

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

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

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

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

            yi += w;
        }
    }

    Log.e("pix", w + " " + h + " " + pix.length);
    bitmap.setPixels(pix, 0, w, 0, 0, w, h);

    return (bitmap);
}

이거 예전에 썼는데...

public static Bitmap myblur(Bitmap image, Context context) {
            final float BITMAP_SCALE = 0.4f;
            final float BLUR_RADIUS = 7.5f;
            int width = Math.round(image.getWidth() * BITMAP_SCALE);
            int height = Math.round(image.getHeight() * BITMAP_SCALE);
            Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
            Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
            RenderScript rs = RenderScript.create(context);
            ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
            Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
            Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
            theIntrinsic.setRadius(BLUR_RADIUS);
            theIntrinsic.setInput(tmpIn);
            theIntrinsic.forEach(tmpOut);
            tmpOut.copyTo(outputBitmap);
            return outputBitmap;
        }

여기에 기재되어 있는 렌더 스크립트를 사용합니다.http://blog.neteril.org/blog/2013/08/12/blurring-images-on-android/

입니다.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;
}
    }

NDK 어프로치를 선택하는 향후의 구글러에 대해서는, 신뢰할 수 있는 스택 블러 알고리즘을 찾을 수 있습니다.여기에서는 SSE에 의존하지 않는 C++ 실장을 찾았습니다.http://www.antigrain.com/__code/include/agg_blur.h.html#stack_blur_rgba32에는 다음과 같은 정적 테이블을 사용한 최적화가 포함되어 있습니다.

static unsigned short const stackblur_mul[255] =
{
    512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512,
    454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512,
    482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456,
    437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512,
    497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328,
    320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456,
    446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335,
    329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512,
    505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405,
    399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328,
    324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271,
    268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456,
    451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388,
    385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335,
    332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292,
    289,287,285,282,280,278,275,273,271,269,267,265,263,261,259
};

static unsigned char const stackblur_shr[255] =
{
    9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,
    17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
    19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
    20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,
    22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
    22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,
    23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
    23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
    23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
    23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24
}; 

멀티코어 시스템의 Stackblur 알고리즘을 수정했습니다.이 알고리즘은 http://vitiy.info/stackblur-algorithm-multi-threaded-blur-for-cpp/에서 확인하실 수 있습니다.코어가 4개인 디바이스가 증가하고 있기 때문에 최적화를 통해 4배의 속도를 얻을 수 있습니다.

Nicolas POMEPUY의 조언. 링크가 도움이 될 것 같습니다: Android 디자인에 대한 블러 효과

github에서의 샘플 프로젝트

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private static Bitmap fastblur16(Bitmap source, int radius, Context ctx) {    
    Bitmap bitmap = source.copy(source.getConfig(), true);    
    RenderScript rs = RenderScript.create(ctx);
    Allocation input = Allocation.createFromBitmap(rs, source, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
    Allocation output = Allocation.createTyped(rs, input.getType());
    ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
    script.setRadius(radius);
    script.setInput(input);
    script.forEach(output);
    output.copyTo(bitmap);
    return bitmap;
}

상기와 같은 RenderScript의 흐림을 다른 답변으로 구현하려고 했습니다.v8 RenderScript 버전 사용이 제한되어 있어 많은 문제가 발생했습니다.

  • 렌더링 스크립트를 사용하려고 할 때마다 삼성 S3가 랜덤으로 크래시됨
  • 다른 디바이스(각종 API 간)에서 랜덤으로 다른 색상의 문제가 발생하였습니다.

느리고 다른 스레드에서 실행되어야 하며 가능하면 사용 전에 지속되어야 하는 지저분한 Java 전용 버전을 공유하고 싶습니다.

private final Paint mPaint = new Paint();

public Bitmap blur(final String pathToBitmap) {
    final BitmapFactory.Options options = new BitmapFactory.Options();
    final Bitmap normalOne = BitmapFactory.decodeFile(pathToBitmap, options);
    final Bitmap resultBitmap = Bitmap.createBitmap(options.outWidth, options.outHeight, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(resultBitmap);
    mPaint.setAlpha(180);
    canvas.drawBitmap(normalOne, 0, 0, mPaint);
    int blurRadius = 12;
    for (int row = -blurRadius; row < blurRadius; row += 2) {
        for (int col = -blurRadius; col < blurRadius; col += 2) {
            if (col * col + row * row <= blurRadius * blurRadius) {
                mPaint.setAlpha((blurRadius * blurRadius) / ((col * col + row * row) + 1) * 2);
                canvas.drawBitmap(normalOne, row, col, mPaint);
            }
        }
    }
    normalOne.recycle();
    return resultBitmap;
}

이 솔루션은 완벽과는 거리가 멀지만 거의 투명한 "선명한" 버전 위에 동일한 이미지의 매우 투명한 버전을 그려낸다는 사실에 따라 상당히 흐릿한 효과를 냅니다.알파는 원점까지의 거리에 따라 달라집니다.

필요에 따라 몇 가지 "매직 넘버"를 조정할 수 있습니다.RenderScript의 v8 지원 버전에 문제가 있는 모든 분들에게 이 "솔루션"을 공유하고자 합니다.

x86 칩셋의 Renderscript 지원 라이브러리에서 아직 문제가 있는 경우 라이브러리 작성자가 이 게시물을 참조하십시오.그가 준비한 수정이 빌드 툴 v20.0.0에 도달하지 못한 것 같습니다.그래서 수동으로 수정하기 위한 파일과 간단한 수정 방법을 제공합니다.

https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby=&sort=&id=71347

Mario Viviani 블로그에서는 17 Android Version에서 이 솔루션을 사용할 수 있습니다.

https://plus.google.com/+MarioViviani/posts/fhuzYkji9zz

또는

https://gist.github.com/Mariuxtheone/903c35b4927c0df18cf8

RenderScript를 사용한 실시간 흐림 오버레이는 충분히 빠른 것 같습니다.

https://github.com/mmin18/RealtimeBlurView

콘트라스트, 휘도, 채도를 조금 줄이면 흐릿한 이미지가 더 예뻐지기 때문에 스택 오버플로우부터 다양한 방법을 조합하여 흐릿한 이미지의 흐림, 밝기 변화, 채도, 콘트라스트, 크기를 다루는 흐림 클래스를 만들었습니다.또한 이미지를 그리기 가능에서 비트맵 또는 그 반대로 변환할 수도 있습니다.

2019년 I/O에서는 다음과 같은 솔루션이 제시되었습니다.

/**
 * Blurs the given Bitmap image
 * @param bitmap Image to blur
 * @param applicationContext Application context
 * @return Blurred bitmap image
 */
@WorkerThread
fun blurBitmap(bitmap: Bitmap, applicationContext: Context): Bitmap {
    lateinit var rsContext: RenderScript
    try {

        // Create the output bitmap
        val output = Bitmap.createBitmap(
                bitmap.width, bitmap.height, bitmap.config)

        // Blur the image
        rsContext = RenderScript.create(applicationContext, RenderScript.ContextType.DEBUG)
        val inAlloc = Allocation.createFromBitmap(rsContext, bitmap)
        val outAlloc = Allocation.createTyped(rsContext, inAlloc.type)
        val theIntrinsic = ScriptIntrinsicBlur.create(rsContext, Element.U8_4(rsContext))
        theIntrinsic.apply {
            setRadius(10f)
            theIntrinsic.setInput(inAlloc)
            theIntrinsic.forEach(outAlloc)
        }
        outAlloc.copyTo(output)

        return output
    } finally {
        rsContext.finish()
    }
}

언급URL : https://stackoverflow.com/questions/2067955/fast-bitmap-blur-for-android-sdk

반응형