import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.opengl.GLException;
import android.opengl.GLSurfaceView;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import java.nio.IntBuffer;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.opengles.GL10;
public class GLSurfaceViewBlur {
public interface BlurCallback {
public void onBlur();
}
/**
* @param context 上下文
* @param glSurfaceView 底层view控件
* @param upperView 需要模糊背景的控件
*/
public static void doBlur(final Context context, final GLSurfaceView glSurfaceView, final ImageView upperView, BlurCallback callback) {
glSurfaceView.queueEvent(new Runnable() {
@Override
public void run() {
EGL10 egl = (EGL10) EGLContext.getEGL();
GL10 gl = (GL10) egl.eglGetCurrentContext().getGL();
Bitmap snapshotBitmap = createBitmapFromGLSurface(0, 0, glSurfaceView.getWidth(), glSurfaceView.getHeight(), gl);
upperView.post(new Runnable() {
@Override
public void run() {
Glide.with(context)
.load(snapshotBitmap).apply(new RequestOptions()
.transforms(new BlurTransformation(context, 25)))
.into(new SimpleTarget() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition super Drawable> transition) {
upperView.setImageDrawable(resource);
if (callback != null) {
callback.onBlur();
}
}
});
}
});
}
});
}
private static Bitmap createBitmapFromGLSurface(int x, int y, int w, int h, GL10 gl)
throws OutOfMemoryError {
int bitmapBuffer[] = new int[w * h];
int bitmapSource[] = new int[w * h];
IntBuffer intBuffer = IntBuffer.wrap(bitmapBuffer);
intBuffer.position(0);
try {
gl.glReadPixels(x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, intBuffer);
int offset1, offset2;
for (int i = 0; i < h; i++) {
offset1 = i * w;
offset2 = (h - i - 1) * w;
for (int j = 0; j < w; j++) {
int texturePixel = bitmapBuffer[offset1 + j];
int blue = (texturePixel >> 16) & 0xff;
int red = (texturePixel << 16) & 0x00ff0000;
int pixel = (texturePixel & 0xff00ff00) | red | blue;
bitmapSource[offset2 + j] = pixel;
}
}
} catch (GLException e) {
return null;
}
return Bitmap.createBitmap(bitmapSource, w, h, Bitmap.Config.ARGB_8888);
}
}
public class BlurTransformation extends BitmapTransformation {
private final String ID = getClass().getName();
private static int MAX_RADIUS = 25;
private static int DEFAULT_SAMPLING = 1;
private Context context;
private int radius; //模糊半径0~25
private int sampling; //取样0~25
public BlurTransformation(Context context) {
this(context, MAX_RADIUS, DEFAULT_SAMPLING);
}
public BlurTransformation(Context context, int radius) {
this(context, radius, DEFAULT_SAMPLING);
}
public BlurTransformation(Context context, int radius, int sampling) {
this.context = context;
this.radius = radius > MAX_RADIUS ? MAX_RADIUS : radius;
this.sampling = sampling > MAX_RADIUS ? MAX_RADIUS : sampling;
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
@Override
protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
int width = toTransform.getWidth();
int height = toTransform.getHeight();
int scaledWidth = width / sampling;
int scaledHeight = height / sampling;
Bitmap bitmap = pool.get(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.scale(1 / (float) sampling, 1 / (float) sampling);
Paint paint = new Paint();
paint.setFlags(Paint.FILTER_BITMAP_FLAG);
canvas.drawBitmap(toTransform, 0, 0, paint);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
bitmap = BlurUtils.rsBlur(context, bitmap, radius);
} else {
bitmap = BlurUtils.blur(bitmap, radius);
}
return bitmap;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof BlurTransformation) {
BlurTransformation other = (BlurTransformation) obj;
return radius == other.radius && sampling == other.sampling;
}
return false;
}
@Override
public int hashCode() {
return Util.hashCode(ID.hashCode(), Util.hashCode(radius, Util.hashCode(sampling)));
}
@Override
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
messageDigest.update((ID + radius * 10 + sampling).getBytes(CHARSET));
}
}
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Build;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
import android.support.annotation.RequiresApi;
public class BlurUtils {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
public static Bitmap rsBlur(Context context, Bitmap toTransform, int radius) {
RenderScript renderScript = RenderScript.create(context);
Allocation input = Allocation.createFromBitmap(renderScript, toTransform);
Allocation output = Allocation.createTyped(renderScript, input.getType());
ScriptIntrinsicBlur scriptIntrinsicBlur = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript));
scriptIntrinsicBlur.setInput(input);
scriptIntrinsicBlur.setRadius(radius);
scriptIntrinsicBlur.forEach(output);
output.copyTo(toTransform);
renderScript.destroy();
return toTransform;
}
public static Bitmap blur(Bitmap toTransform, int radius) {
if (radius < 1) {
return (null);
}
int w = toTransform.getWidth();
int h = toTransform.getHeight();
int[] pix = new int[w * h];
toTransform.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++) {
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;
}
}
toTransform.setPixels(pix, 0, w, 0, 0, w, h);
return toTransform;
}
}
部分手机会出现黑屏问题,有更好的方案欢迎留言