public class GaussFilterTask extends AsyncTask<Void, Double, Void> {
private Bitmap bitmap;
private Bitmap target;
private Context context;
private View imageTarget;
public GaussFilterTask(Context context, ImageView imageTarget) {
super();
this.context = context;
Drawable drawable = imageTarget.getDrawable();
this.imageTarget = imageTarget;
bitmap = ((BitmapDrawable) drawable).getBitmap();
bitmap = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth() / 20, bitmap.getHeight() / 20, false);
}
public GaussFilterTask(Context context, View imageTarget, Bitmap bitmap) {
super();
this.context = context;
this.imageTarget = imageTarget;
this.bitmap = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth() / 20, bitmap.getHeight() / 20, false);
}
@Override
protected Void doInBackground(Void... params) {
gaussBlur(bitmap, target);//调用高斯模糊方法
return null;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
target = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
}
@Override
protected void onProgressUpdate(Double... values) {
super.onProgressUpdate(values);
}
@TargetApi(Build.VERSION_CODES.DONUT)
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (imageTarget instanceof ImageView) {
((ImageView) imageTarget).setImageDrawable(new BitmapDrawable(context.getResources(), target));
} else {
imageTarget.setBackgroundDrawable(new BitmapDrawable(context.getResources(), target));
}
}
private void gaussBlur(Bitmap src, Bitmap target) {
if (src.getConfig() != Bitmap.Config.ARGB_8888) {//简化考虑,只支持ARGB8888格式的Bitmap,即 透明、红、绿、蓝四个通道各占一个字节
return;
}
int boxWidth = 7;//盒子大小为7x7
int boxHeight = 7;
GaussFilter filter = new GaussFilter(boxHeight, boxWidth);//实例化GaussFilter,并传递给filter()方法
for (int i = 0; i < src.getHeight(); i++) {
for (int j = 0; j < src.getWidth(); j++) {
int meanPixel = filter(boxWidth, boxHeight, i, j, src, filter);
target.setPixel(j, i, meanPixel);
}
}
}
/**
* 根据滤波模板进行滤波
*
* @param boxWidth 盒子宽度(此处为3)
* @param boxHeight 盒子高度(此处为3)
* @param rowIndex targetBitmap的目标像素点在第xx行
* @param colIndex targetBitmap的目标像素点在第xx列
* @param src 源Bitmap
* @param filter 滤波模板
* @return
*/
private int filter(int boxWidth, int boxHeight, int rowIndex, int colIndex, Bitmap src, Filter filter) {
if (boxWidth % 2 == 0 || boxHeight % 2 == 0)
return 0;
int targetPixel = 0xff000000;//计算的结果
int redSum = 0;
int greenSum = 0;
int blueSum = 0;
int temp;
for (int i = rowIndex - boxHeight / 2, boxRow = 0; i <= rowIndex + boxHeight / 2; i++, boxRow++) {
for (int j = colIndex - boxWidth / 2, boxCol = 0; j <= colIndex + boxWidth / 2; j++, boxCol++) {
if (i < 0 || i >= src.getHeight() || j < 0 || j >= src.getWidth()) //越界
temp = src.getPixel(colIndex, rowIndex);
else
temp = src.getPixel(j, i);//依次取出盒子内的像素点
redSum += ((temp & 0x00ff0000) >> 16) * filter.weight(boxRow, boxCol);//求均值,先计算sum,对于 均值模糊, 这里的weight为1
greenSum += ((temp & 0x0000ff00) >> 8) * filter.weight(boxRow, boxCol);//求均值,先计算sum,对于 均值模糊, 这里的weight为1
blueSum += (temp & 0x000000ff) * filter.weight(boxRow, boxCol);//求均值,先计算sum,对于 均值模糊, 这里的weight为1
}
}
int meanRed = ((int) (redSum * 1.0 / filter.total())) << 16;//ARGB red通道需要左移16bit归位,对于 均值模糊, 这里的total为9
int meanGreen = ((int) (greenSum * 1.0 / filter.total())) << 8;//ARGB green通道需要左移8bit归位,对于 均值模糊, 这里的total为9
int meanBlue = ((int) (blueSum * 1.0 / filter.total()));//,对于 均值模糊, 这里的total为9
targetPixel = (targetPixel | meanRed | meanGreen | meanBlue);//或运算 将3个求均值的结果合一
return targetPixel;
}
/**
* Created by zjl on 2016/12/13.
* 使用二项式分布逼近的高斯滤波器
*/
private class GaussFilter implements Filter {
private int width;
private int height;
public GaussFilter(int boxHeight, int boxWidth) {
this.height = boxHeight;
this.width = boxWidth;
}
@Override
public int weight(int rowIndex, int colIndex) {
int me = C(width - 1, colIndex);
return me * C(height - 1, rowIndex);
}
@Override
public int total() {
int result = (int) Math.pow(2, width + height - 2);
return result;
}
private int C(int n, int k) { //n次二项展开式,第k项
if (k <= 0)
return 1;
if (k > n / 2)
return C(n, n - k);
int result = 1;
for (int i = 1; i <= k; i++)
result *= (n - i + 1);
for (int i = 1; i <= k; i++)
result /= i;
return result;
}
}
public interface Filter {
int weight(int rowIndex, int colIndex);//盒子元素与滤波模板元素做乘积最后求平均,在均值模糊中,这里的weight为1
int total();//前面求出sum然后除以total求出最后的平均颜色值
}
}