图片处理的几种算法(毛玻璃效果,高斯模糊效果,旧时光效果,lomo效果,暖意效果)


毛玻璃效果:高斯模糊效果:


//高斯模糊,毛玻璃
//低于Android4.2可以用Java原生代码实现。但是效率会低不少:这完全是一种妥协的方式,不推荐
public 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];
		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++) {
				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;
			}
		}

		bitmap.setPixels(pix, 0, w, 0, 0, w, h);
		return (bitmap);
	}
// RenderScript的这个方法需要Android API17

private void blur(Bitmap bkg, View view, float radius) {
    Bitmap overlay = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(overlay);
    canvas.drawBitmap(bkg, -view.getLeft(), -view.getTop(), null);
    RenderScript rs = RenderScript.create(this);
    Allocation overlayAlloc = Allocation.createFromBitmap(rs, overlay);
    ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(rs, overlayAlloc.getElement());
    blur.setInput(overlayAlloc);
    blur.setRadius(radius);
    blur.forEach(overlayAlloc);
    overlayAlloc.copyTo(overlay);
    view.setBackground(new BitmapDrawable(getResources(), overlay));
    rs.destroy();
}

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

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

//高斯模糊
public static void gaussBlur(int[] data, int width, int height, int radius,float sigma) {

	float pa = (float) (1 / (Math.sqrt(2 * Math.PI) * sigma));
	float pb = -1.0f / (2 * sigma * sigma);

	// generate the Gauss Matrix
	float[] gaussMatrix = new float[radius * 2 + 1];
	float gaussSum = 0f;
	for (int i = 0, x = -radius; x <= radius; ++x, ++i) {
		float g = (float) (pa * Math.exp(pb * x * x));
		gaussMatrix[i] = g;
		gaussSum += g;
	}

	for (int i = 0, length = gaussMatrix.length; i < length; ++i) {
		gaussMatrix[i] /= gaussSum;
	}

	// x direction
	for (int y = 0; y < height; ++y) {
		for (int x = 0; x < width; ++x) {
			float r = 0, g = 0, b = 0;
			gaussSum = 0;
			for (int j = -radius; j <= radius; ++j) {
				int k = x + j;
				if (k >= 0 && k < width) {
					int index = y * width + k;
					int color = data[index];
					int cr = (color & 0x00ff0000) >> 16;
					int cg = (color & 0x0000ff00) >> 8;
					int cb = (color & 0x000000ff);

					r += cr * gaussMatrix[j + radius];
					g += cg * gaussMatrix[j + radius];
					b += cb * gaussMatrix[j + radius];

					gaussSum += gaussMatrix[j + radius];
				}
			}

			int index = y * width + x;
			int cr = (int) (r / gaussSum);
			int cg = (int) (g / gaussSum);
			int cb = (int) (b / gaussSum);
			
			data[index] = cr << 16 | cg << 8 | cb | 0xff000000;
		}
	}

	// y direction
	for (int x = 0; x < width; ++x) {
		for (int y = 0; y < height; ++y) {
			float r = 0, g = 0, b = 0;
			gaussSum = 0;
			for (int j = -radius; j <= radius; ++j) {
				int k = y + j;
				if (k >= 0 && k < height) {
					int index = k * width + x;
					int color = data[index];
					int cr = (color & 0x00ff0000) >> 16;
					int cg = (color & 0x0000ff00) >> 8;
					int cb = (color & 0x000000ff);

					r += cr * gaussMatrix[j + radius];
					g += cg * gaussMatrix[j + radius];
					b += cb * gaussMatrix[j + radius];

					gaussSum += gaussMatrix[j + radius];
				}
			}

			int index = y * width + x;
			int cr = (int) (r / gaussSum);
			int cg = (int) (g / gaussSum);
			int cb = (int) (b / gaussSum);
			data[index] = cr << 16 | cg << 8 | cb | 0xff000000;
		}
	}
}




旧时光效果:

/**
* 旧时光特效
*
* @param bmp
*            原图片
* @return 旧时光特效图片
*/
public static Bitmap oldTimeFilter (Bitmap bmp)
{
    int width = bmp.getWidth();
    int height = bmp.getHeight();
    Bitmap bitmap = Bitmap.createBitmap (width, height, Bitmap.Config.RGB_565);
    int pixColor = 0;
    int pixR = 0;
    int pixG = 0;
    int pixB = 0;
    int newR = 0;
    int newG = 0;
    int newB = 0;
    int[] pixels = new int[width * height];
    bmp.getPixels (pixels, 0, width, 0, 0, width, height);
    for (int i = 0; i < height; i++)
    {
        for (int k = 0k < width; k++)
        {
            pixColor = pixels[width * i + k];
            pixR = Color.red (pixColor);
            pixG = Color.green (pixColor);
            pixB = Color.blue (pixColor);
            newR = (int) (0.393 * pixR + 0.769 * pixG + 0.189 * pixB);
            newG = (int) (0.349 * pixR + 0.686 * pixG + 0.168 * pixB);
            newB = (int) (0.272 * pixR + 0.534 * pixG + 0.131 * pixB);
            int newColor = Color.argb (255, newR > 255 ? 255 : newR, newG > 255 ? 255 : newG, newB > 255 ? 255 : newB);
            pixels[width * i + k] = newColor;
        }
    }
    bitmap.setPixels (pixels, 0, width, 0, 0, width, height);
    return bitmap;
}



暖意效果:


/**
* 暖意特效
*
* @param bmp
*            原图片
* @param centerX
*            光源横坐标
* @param centerY
*            光源纵坐标
* @return 暖意特效图片
*/
public static Bitmap warmthFilter (Bitmap bmp, int centerX, int centerY)
{
    final int width = bmp.getWidth();
    final int height = bmp.getHeight();
    Bitmap bitmap = Bitmap.createBitmap (width, height, Bitmap.Config.RGB_565);
    int pixR = 0;
    int pixG = 0;
    int pixB = 0;
    int pixColor = 0;
    int newR = 0;
    int newG = 0;
    int newB = 0;
    int radius = Math.min (centerX, centerY);
    final float strength = 150F;
    // 光照强度 100~150
    int[] pixels = new int[width * height];
    bmp.getPixels (pixels, 0, width, 0, 0, width, height);
    int pos = 0;
    for (int i = 1, length = height - 1; i < length; i++)
    {
        for (int k = 1, len = width - 1; k < len; k++)
        {
            pos = i * width + k;
            pixColor = pixels[pos];
            pixR = Color.red (pixColor);
            pixG = Color.green (pixColor);
            pixB = Color.blue (pixColor);
            newR = pixR;
            newG = pixG;
            newB = pixB;
            // 计算当前点到光照中心的距离,平面座标系中求两点之间的距离
            int distance = (int) (Math.pow ( (centerY - i), 2) + Math.pow (centerX - k, 2) );
            if (distance < radius * radius)
            {
                // 按照距离大小计算增加的光照值
                int result = (int) (strength * (1.0 - Math.sqrt (distance) / radius) );
                newR = pixR + result;
                newG = pixG + result;
                newB = pixB + result;
            }
            newR = Math.min (255, Math.max (0, newR) );
            newG = Math.min (255, Math.max (0, newG) );
            newB = Math.min (255, Math.max (0, newB) );
            pixels[pos] = Color.argb (255, newR, newG, newB);
        }
    }
    bitmap.setPixels (pixels, 0, width, 0, 0, width, height);

    return bitmap;
}





lomo效果


/**
* LOMO特效
*
* @param bitmap
*            原图片
* @return LOMO特效图片
*/
public static Bitmap lomoFilter (Bitmap bitmap)
{
    int width = bitmap.getWidth();
    int height = bitmap.getHeight();
    int dst[] = new int[width * height];
    bitmap.getPixels (dst, 0, width, 0, 0, width, height);
    int ratio = width > height ? height * 32768 / width : width * 32768 / height;
    int cx = width >> 1;
    int cy = height >> 1;
    int max = cx * cx + cy * cy;
    int min = (int) (max * (1 - 0.8f) );
    int diff = max - min;
    int ri, gi, bi;
    int dx, dy, distSq, v;
    int R, G, B;
    int value;
    int pos, pixColor;
    int newR, newG, newB;
    for (int y = 0; y < height; y++)
    {

        for (int x = 0; x < width; x++)
        {
            pos = y * width + x;
            pixColor = dst[pos];
            R = Color.red (pixColor);
            G = Color.green (pixColor);
            B = Color.blue (pixColor);
            value = R < 128 ? R : 256 - R;
            newR = (value * value * value) / 64 / 256;
            newR = (R < 128 ? newR : 255 - newR);
            value = G < 128 ? G : 256 - G;
            newG = (value * value) / 128;
            newG = (G < 128 ? newG : 255 - newG);
            newB = B / 2 + 0x25;
            // ==========边缘黑暗==============//
            dx = cx - x;
            dy = cy - y;
            if (width > height)
            {
                dx = (dx * ratio) >> 15;
            }
            else
            {
                dy = (dy * ratio) >> 15;
            }
            distSq = dx * dx + dy * dy;
            if (distSq > min)
            {
                v = ( (max - distSq) << 8) / diff;
                v *= v;
                ri = newR * v >> 16;
                gi = newG * v >> 16;
                bi = newB * v >> 16;
                newR = ri > 255 ? 255 : (ri < 0 ? 0 : ri);
                newG = gi > 255 ? 255 : (gi < 0
                                         ? 0 : gi);
                newB = bi > 255 ? 255 : (bi < 0 ? 0 : bi);
            }
            // ==========边缘黑暗end==============//
            dst[pos] = Color.rgb (newR, newG, newB);
        }
    }
    Bitmap acrossFlushBitmap = Bitmap.createBitmap (width, height, Bitmap.Config.RGB_565);
    acrossFlushBitmap.setPixels (dst, 0, width, 0, 0, width, height);
    return acrossFlushBitmap;
}






高斯模糊效果:
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值