java实现Android高斯模糊思路

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求出最后的平均颜色值
    }

}

 

转载于:https://my.oschina.net/kkk3208/blog/891778

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值