Android素描算法及实现手指在图片上左右滑动调节图片透明度,最终实现类似调节素描浓度的效果

一、前期基础知识储备

UI掌握PS这一逆天的软件,可以实现将图片转化为素描或者水彩的效果,以素描为例:

  1. 在Photoshop中打开一张人物照片,按下快捷键“Ctrl+Shift+U”,把它转换成黑白颜色;
  2. 复制图层,得到一个副本图层。按下快捷键“Ctrl+I”,将副本图层转换成负片效果;
  3. 将副本图层下拉菜单选为“颜色减淡”,这时图片会亮得几乎什么也看不见,不要急,慢慢来;
  4. 在“滤镜”菜单下选择“模糊→高斯模糊”,模糊半径值可根据你需要的素描线条粗细深浅来设置。到此素描画像工作就完成了。

我们将以上四步进行抽象,得到将图片转为素描效果的步骤即为:

  1. 去色,将图片变为灰度图,即黑白图;
  2. 反相,得到每个像素的补色,具体效果就像照片的底片;
  3. 高斯模糊,把反相后的像素值平均一下;
  4. 颜色减淡,将第1步中的像素和第3步得到的像素值进行计算。

在Android图像处理领域,我们可以使用像素点分析的方法实现上述的效果组合。下面,用代码实现上述过程

二、上代码,具体实现素描算法

1)去色,获取黑白图;

	public static int[] discolor(Bitmap bitmap) {
 
		int picHeight = bitmap.getHeight();
		int picWidth = bitmap.getWidth();
 
		int[] pixels = new int[picWidth * picHeight];
		bitmap.getPixels(pixels, 0, picWidth, 0, 0, picWidth, picHeight);
 
		for (int i = 0; i < picHeight; ++i) {
			for (int j = 0; j < picWidth; ++j) {
				int index = i * picWidth + j;
				int color = pixels[index];
				int r = (color & 0x00ff0000) >> 16;
				int g = (color & 0x0000ff00) >> 8;
				int b = (color & 0x000000ff);
				int grey = (int) (r * KR + g * KG + b * KB);
				pixels[index] = grey << 16 | grey << 8 | grey | 0xff000000;
			}
		}
		
		return pixels;
 
	}

2)反相,得到图片的底图;

public static int[] reverseColor(int[] pixels) {
		
		int length = pixels.length;
		int[] result = new int[length];
		for (int i = 0; i < length; ++i) {
			int color = pixels[i];
			
			int r = 255 - (color & 0x00ff0000) >> 16;
			int g = 255 - (color & 0x0000ff00) >> 8;
			int b = 255 - (color & 0x000000ff);
			result[i] = r << 16 | g << 8 | b | 0xff000000;
		}
		return result;
		
	}

3)高斯模糊,得到反高斯图像;

	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;
			}
		}
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值