Android GLSurfaceView模糊效果
16lz
2021-01-23
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; }}
部分手机会出现黑屏问题,有更好的方案欢迎留言
更多相关文章
- Android(Java):自定义控件
- android 获取界面上所有控件
- Android开发——控件基础(七)ListView组件:示例代码
- Android实现圆形头像-使用自定义控件
- android -布局控件禁用多点触控
- 1、ListView自定义控件下拉刷新(一)
- Android使用AttributeSet自定义控件的方法
- android自定义控件
- 常见UI控件的使用-富文本、textview