最近在做一款叫叽叽的App(男银懂的),其中有一个功能需要对图片处理实现毛玻璃的特效
进过一番预研,找到了3中实现方案,其中各有优缺点:
1、如果系统的api在16以上,可以使用系统提供的方法直接处理图片
if (VERSION.SDK_INT > 16) { Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true); final RenderScript rs = RenderScript.create(context); final Allocation input = Allocation.createFromBitmap(rs, sentBitmap, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); final Allocation output = Allocation.createTyped(rs, input.getType()); final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); script.setRadius(radius /* e.g. 3.f */); script.setInput(input); script.forEach(output); output.copyTo(bitmap); return bitmap; }
2、 如果Api条件不满足,可以使用如下方法
@SuppressLint("NewApi") public static Bitmap fastblur(Context context, Bitmap sentBitmap, int radius) { 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 temp = 256 * divsum; int dv[] = new int[temp]; for (i = 0; i < temp; 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); }
3、以上方法都存在一个问题,性能较低,下面提供一个C实现

static int* StackBlur(int* pix, int w, int h, int radius) { int wm = w - 1; int hm = h - 1; int wh = w * h; int div = radius + radius + 1; int *r = (int *)malloc(wh * sizeof(int)); int *g = (int *)malloc(wh * sizeof(int)); int *b = (int *)malloc(wh * sizeof(int)); int rsum, gsum, bsum, x, y, i, p, yp, yi, yw; int *vmin = (int *)malloc(MAX(w,h) * sizeof(int)); int divsum = (div + 1) >> 1; divsum *= divsum; int *dv = (int *)malloc(256 * divsum * sizeof(int)); for (i = 0; i < 256 * divsum; i++) { dv[i] = (i / divsum); } yw = yi = 0; int(*stack)[3] = (int(*)[3])malloc(div * 3 * sizeof(int)); 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 + (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); return(pix); }
相关推荐
"Android背景图片模糊虚化Demo"是针对这一功能的实例展示,旨在帮助开发者理解和实现类似效果。以下是对这个主题的详细解析: 1. **Android模糊效果原理** - Android中的模糊效果通常是通过图像处理技术实现的,如...
其次,**背景虚化**在Android中可通过多种技术实现。一种常见方法是使用模糊库,比如`androidx.core.graphics.drawable.BlurMaskFilterDrawable`或第三方库`BlurKit`,它们可以对背景图像进行实时模糊处理。另一种...
毛玻璃效果 背景虚化实现,封装好直接调用接口即可 简单 方便
利用OpenCV4Android实现一个带有人脸背景虚化功能的拍照APP,采用的图像处理算法是高斯模糊。详细的博客讲述请看:http://blog.csdn.net/wblgers1234/article/details/77842469
css3背景虚化效果是一款css3 js实现的背景虚化效果,支持添加气泡、隐藏标题等功能。 css3背景虚化效果演示图: 点击查看演示
在图像处理领域,背景虚化是一种常见的技术,用于突出图像中的主体,使背景变得模糊,从而营造出类似专业摄影中的景深效果。美图秀秀作为一款流行的照片编辑软件,其背景虚化功能深受用户喜爱。本文将详细介绍如何在...
在本文中,我们将深入探讨如何使用QT C++库来实现毛玻璃效果,即窗口的透明度与模糊结合的视觉效果。这种技术常用于现代UI设计,以提供更优雅、时尚的用户界面。我们将通过分析“glassui”这个压缩包中的源代码来...
在Android开发中,有时为了提升用户体验和视觉效果,我们需要对布局的背景进行模糊化处理。模糊化处理可以使应用界面更具层次感,突出显示主要内容。本文将详细讲解如何在Android中实现这一功能。 首先,我们需要...
在Android社区,有许多优秀的第三方库可以帮助我们实现复杂的图片处理效果,如`android-image-filter`库,它提供了一系列的图片滤镜效果,包括羽化。通过这些库,开发者可以轻松地添加羽化效果,而不必自己实现底层...
css3背景虚化模糊效果
标题中的“窗口毛玻璃效果(c++源码加程序)”指的是使用C++编程语言实现的一种视觉效果,这种效果通常被称作“模糊效果”或“毛玻璃效果”。在现代操作系统如Windows 10中,这种效果常用于窗口背景,使得窗口下方的...
`blurUtils`是一个专门为Android开发者设计的工具包,用于快速实现背景模糊效果。它包含了一些预定义的方法,可以方便地将一个Bitmap对象模糊化。使用这个工具包,你可以避免编写复杂的图像处理代码,只需几行简单的...
在Swift开发中,实现类似美图软件的背景虚化效果是一项常见的图像处理任务,它可以为应用增添专业级的摄影感。本教程将引导你通过三步实现这一功能,让你的应用也能拥有高端的视觉体验。 第一步:理解背景虚化原理 ...
首先,虚化效果是一种摄影和图像处理技术,通常通过大光圈、浅景深或者后期处理实现。在这些PPT背景图片中,设计师可能使用了类似的技术,将大桥的前景或背景模糊,使主体——大桥——更为醒目,同时也创造出一种...
Android Dialog 背景模糊化效果实现方法 Android Dialog 背景模糊化效果实现方法是指在 Android 应用程序中,为 Dialog 窗口设置模糊化的背景图片,以达到视觉上的美化和用户体验的提升。本文将详细介绍 Android ...
在Android开发中,模糊背景是一种常见的视觉效果,用于提升应用界面的美观度和用户体验。它可以使主内容区域更突出,同时增添一种高级感。本文将深入探讨如何在Android平台上实现模糊背景,包括基本原理、使用的技术...
动态加载页面主要用于解决大型应用程序启动时由于加载大量资源导致的延迟问题,而背景虚化则能为用户提供更加美观且专业的界面效果。 **动态加载页面** 动态加载页面的核心思想是在程序运行时按需加载用户界面(UI...
讲干货,不啰嗦,有时候前端会遇到背景虚化但要求内容清晰的需求,先看效果: 以下为具体实现: <!DOCTYPE html> <html lang=en> <head> <meta charset=UTF-8> <title>背景虚化</...