Android毛玻璃效果实现

来源:互联网 发布:管家婆数据库安装教程 编辑:程序博客网 时间:2024/03/29 08:34

最近在研究Android的毛玻璃效果,图片加上毛玻璃的效果很不错,lipeil的博文给出了JAVA和C实现的方法,由于JAVA方法实现性能较低,本文将其中的C实现的方法修改为JNI可调用的方法,可以以较高的性能实现图片的毛玻璃效果处理。

#include <jni.h>#include <stdio.h>#include <malloc.h>#define MAX(a,b)((a>b)?(a):(b))#define MIN(a,b)((a<b)?(a):(b))#define ABS(x) ((x)>=0 ? (x):(-(x)))JNIEXPORT jintArray  JNICALL Java_com_clazz_BulrManager_StackBlur(JNIEnv *env, jobject obj, jintArray array1, jint w, jint h, jint radius){const jsize length = env->GetArrayLength(array1);jintArray newArray = env->NewIntArray(length);jint *pix;pix = env->GetIntArrayElements(array1, NULL);jint *narr = env->GetIntArrayElements(newArray, NULL);    jint wm = w - 1;    jint hm = h - 1;    jint wh = w * h;    jint div = radius + radius + 1;    jint *r = (jint *)malloc(wh * sizeof(jint));    jint *g = (jint *)malloc(wh * sizeof(jint));    jint *b = (jint *)malloc(wh * sizeof(jint));    jint rsum, gsum, bsum, x, y, i, p, yp, yi, yw;    jint *vmin = (jint *)malloc(MAX(w,h) * sizeof(jint));    jint divsum = (div + 1) >> 1;    divsum *= divsum;    jint *dv = (jint *)malloc(256 * divsum * sizeof(jint));    for (i = 0; i < 256 * divsum; i++) {        dv[i] = (i / divsum);    }    yw = yi = 0;    jint(*stack)[3] = (jint(*)[3])malloc(div * 3 * sizeof(jint));    jint stackpointer;    jint stackstart;    jint *sir;    jint rbs;    jint r1 = radius + 1;    jint routsum, goutsum, boutsum;    jint 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 + (MIN(wm, MAX(i, 0)))];            sir = stack[i + radius];            sir[0] = (p & 0xff0000) >> 16;            sir[1] = (p & 0x00ff00) >> 8;            sir[2] = (p & 0x0000ff);            rbs = r1 - 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] = 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 = MAX(0, yp) + x;            sir = stack[i + radius];            sir[0] = r[yi];            sir[1] = g[yi];            sir[2] = b[yi];            rbs = r1 - 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] = 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;        }    }    free(r);    free(g);    free(b);    free(vmin);    free(dv);    free(stack);    for(jint x = 0; x < length; x ++){    narr[x]=pix[x];    }    env->ReleaseIntArrayElements(newArray, narr, NULL);    env->ReleaseIntArrayElements(array1, pix, NULL);    return newArray;}jint JNI_OnLoad(JavaVM *vm, void *reserved){void *venv;if(vm->GetEnv((void**)&venv, JNI_VERSION_1_4)!=JNI_OK){return -1;}return JNI_VERSION_1_4;}

JAVA层调用

Bitmap mBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.image); Bitmap bitmap = mBitmap.copy(mBitmap.getConfig(), true);//做一份Bitmap拷贝,拷贝的图片是可以被修改的。int w = bitmap.getWidth();  int h = bitmap.getHeight();  int[] pix = new int[w*h];bitmap.getPixels(pix, 0, w, 0, 0, w, h);bitmap.setPixels(BulrManager.StackBlur(pix, w, h, 3), 0, w, 0, 0, w, h);//调用jni中的C方法处理图片,并修改图片的pixels值实现毛玻璃效果iv.setImageBitmap(bitmap);if(mBitmap!=null && !mBitmap.isRecycled()){      mBitmap.recycle();}

实现的效果图:


代码下载地址:源码下载


1 0
原创粉丝点击