博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
图片处理的几种算法(毛玻璃效果,高斯模糊效果,旧时光效果,lomo效果,暖意效果)
阅读量:4291 次
发布时间:2019-05-27

本文共 17438 字,大约阅读时间需要 58 分钟。

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

//高斯模糊,毛玻璃//低于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 API17private 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;}

高斯模糊效果:

转载地址:http://wcegi.baihongyu.com/

你可能感兴趣的文章
ffmpeg源码分析之媒体打开过程
查看>>
Ubuntu/centos/redhat/SUSE sipp安装(带rtp支持,3.5.1版本)
查看>>
周鸿祎:很多程序员聪明,但我一看就知道他不会成功
查看>>
编译程序遇到问题 relocation R_X86_64_32 against `.rodata' can not be used when making a shared object;
查看>>
Const指针 、 指向const的指针 、引用、指针
查看>>
GDB调试命令
查看>>
常见数据类型的字节数
查看>>
gcc/g++ 编译常见问题
查看>>
【设计模式】 工厂模式实例 C++ , 利用工厂模式写一个计算器
查看>>
opencv
查看>>
【图像处理】 一、OSTU分割
查看>>
Android常用的框架有哪些
查看>>
SSL 证书创建与部署
查看>>
学习搭建人工智能环境遇到的问题
查看>>
自己编写的计算器
查看>>
视频物体检测
查看>>
Tomcat启动遇到的问题
查看>>
Gradle-gradlew
查看>>
grpc-整合gradle与代码生成
查看>>
grpc-gradle与grpc流程完美整合(3)
查看>>