Android高斯模糊在java层面上的两种实现方式

第一种是依赖于support-v8的实现如下

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.support.annotation.FloatRange;
import android.support.v8.renderscript.Allocation;
import android.support.v8.renderscript.Element;
import android.support.v8.renderscript.RenderScript;
import android.support.v8.renderscript.ScriptIntrinsicBlur;


import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
import com.bumptech.glide.request.target.Target;


/**
 * Georgia Blur Transformation
 * <p>
 * @author Ligboy.Liu ligboy@gmail.com.
 */
public class BlurTransformation extends BitmapTransformation {


    private static final String ID = "org.ligboy.glide.BlurTransformation";


    public static final float DEFAULT_RADIUS = 25.0f;
    public static final float MAX_RADIUS = 25.0f;
    private static final float DEFAULT_SAMPLING = 1.0f;


    private Context mContext;
    private float mSampling = DEFAULT_SAMPLING;
    private float mRadius;
    private int mColor;


    public static class Builder {


        private Context mContext;
        private float mRadius = DEFAULT_RADIUS;
        private int mColor = Color.TRANSPARENT;


        public Builder(Context mContext) {
            this.mContext = mContext;
        }


        public float getRadius() {
            return mRadius;
        }


        public Builder setRadius(float radius) {
            mRadius = radius;
            return this;
        }


        public int getColor() {
            return mColor;
        }


        public Builder setColor(int color) {
            mColor = color;
            return this;
        }


        public BlurTransformation build() {
            return new BlurTransformation(mContext, mRadius, mColor);
        }


    }


    /**
     *
     * @param context Context
     * @param radius The blur's radius.
     * @param color The color filter for blurring.
     */
    public BlurTransformation(Context context, @FloatRange(from = 0.0f) float radius, int color) {
        super(context);
        mContext = context;
        if (radius > MAX_RADIUS) {
            mSampling = radius / 25.0f;
            mRadius = MAX_RADIUS;
        } else {
            mRadius = radius;
        }
        mColor = color;
    }
    /**
     *
     * @param context Context
     * @param radius The blur's radius.
     */
    public BlurTransformation(Context context, @FloatRange(from = 0.0f) float radius) {
        this(context, radius, Color.TRANSPARENT);
    }


    public BlurTransformation(Context context) {
        this(context, DEFAULT_RADIUS);
    }


    /**
     * Transforms the given {@link Bitmap} based on the given dimensions and returns the transformed
     * result.
     * <p/>
     * <p>
     * The provided Bitmap, toTransform, should not be recycled or returned to the pool. Glide will automatically
     * recycle and/or reuse toTransform if the transformation returns a different Bitmap. Similarly implementations
     * should never recycle or return Bitmaps that are returned as the result of this method. Recycling or returning
     * the provided and/or the returned Bitmap to the pool will lead to a variety of runtime exceptions and drawing
     * errors. See #408 for an example. If the implementation obtains and discards intermediate Bitmaps, they may
     * safely be returned to the BitmapPool and/or recycled.
     * </p>
     * <p/>
     * <p>
     * outWidth and outHeight will never be {@link Target#SIZE_ORIGINAL}, this
     * class converts them to be the size of the Bitmap we're going to transform before calling this method.
     * </p>
     *
     * @param pool        A {@link BitmapPool} that can be used to obtain and
     *                    return intermediate {@link Bitmap}s used in this transformation. For every
     *                    {@link Bitmap} obtained from the pool during this transformation, a
     *                    {@link Bitmap} must also be returned.
     * @param toTransform The {@link Bitmap} to transform.
     * @param outWidth    The ideal width of the transformed bitmap (the transformed width does not need to match exactly).
     * @param outHeight   The ideal height of the transformed bitmap (the transformed heightdoes not need to match
     */
    @Override
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        boolean needScaled = mSampling == DEFAULT_SAMPLING;
        int originWidth = toTransform.getWidth();
        int originHeight = toTransform.getHeight();
        int width, height;
        if (needScaled) {
            width = originWidth;
            height = originHeight;
        } else {
            width = (int) (originWidth / mSampling);
            height = (int) (originHeight / mSampling);
        }
        //find a re-use bitmap
        Bitmap bitmap = pool.get(width, height, Bitmap.Config.ARGB_8888);
        if (bitmap == null) {
            bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        }


        Canvas canvas = new Canvas(bitmap);
        if (mSampling != DEFAULT_SAMPLING) {
            canvas.scale(1 / mSampling, 1 / mSampling);
        }
        Paint paint = new Paint();
        paint.setFlags(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG);
        PorterDuffColorFilter filter =
                new PorterDuffColorFilter(mColor, PorterDuff.Mode.SRC_ATOP);
        paint.setColorFilter(filter);
        canvas.drawBitmap(toTransform, 0, 0, paint);
// TIPS: Glide will take care of returning our original Bitmap to the BitmapPool for us,
// we needn't to recycle it.
//        toTransform.recycle();  <--- Just for tips. by Ligboy


        RenderScript rs = RenderScript.create(mContext);
        Allocation input = Allocation.createFromBitmap(rs, bitmap, Allocation.MipmapControl.MIPMAP_NONE,
                Allocation.USAGE_SCRIPT);
        Allocation output = Allocation.createTyped(rs, input.getType());
        ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));


        blur.setInput(input);
        blur.setRadius(mRadius);
        blur.forEach(output);
        output.copyTo(bitmap);


        rs.destroy();


        if (needScaled) {
            return bitmap;
        } else {
            Bitmap scaled = Bitmap.createScaledBitmap(bitmap, originWidth, originHeight, true);
            bitmap.recycle();
            return scaled;
        }
    }


    /**
     * A method to get a unique identifier for this particular transformation that can be used as part of a cache key.
     * The fully qualified class name for this class is appropriate if written out, but getClass().getName() is not
     * because the name may be changed by proguard.
     * <p/>
     * <p>
     * If this transformation does not affect the data that will be stored in cache, returning an empty string here
     * is acceptable.
     * </p>
     *
     * @return A string that uniquely identifies this transformation.
     */
    @Override
    public String getId() {
        StringBuilder sb = new StringBuilder(ID);
        sb.append('-').append(mRadius).append('-').append(mColor);
        return sb.toString();
    }
}

然后在build.gradle上的defaultConfig上配置如下两排代码

defaultConfig {

        renderscriptTargetApi 20
        renderscriptSupportModeEnabled true

}

在activity里面用glide加载网络图片并模糊

Glide.with(Context).load(url).asBitmap().transform(new BlurTransformation(Context, 25)).into(ivbg);

这是一种方法。

第二种

package com.wbkj.artmss.Weight;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
import android.support.annotation.FloatRange;

import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
import com.bumptech.glide.request.target.Target;

public class FastBlur extends BitmapTransformation {

    private static final String ID = "org.ligboy.glide.BlurTransformation";

    public static final float DEFAULT_RADIUS = 25.0f;
    public static final float MAX_RADIUS = 25.0f;
    private static final float DEFAULT_SAMPLING = 1.0f;

    private Context mContext;
    private float mSampling = DEFAULT_SAMPLING;
    private float mRadius;
    private int mColor;

    public static class Builder {

        private Context mContext;
        private float mRadius = DEFAULT_RADIUS;
        private int mColor = Color.TRANSPARENT;

        public Builder(Context mContext) {
            this.mContext = mContext;
        }

        public float getRadius() {
            return mRadius;
        }

        public Builder setRadius(float radius) {
            mRadius = radius;
            return this;
        }

        public int getColor() {
            return mColor;
        }

        public Builder setColor(int color) {
            mColor = color;
            return this;
        }

        public FastBlur build() {
            return new FastBlur(mContext, mRadius, mColor);
        }

    }

    /**
     * @param context Context
     * @param radius  The blur's radius.
     * @param color   The color filter for blurring.
     */
    public FastBlur(Context context, @FloatRange(from = 0.0f) float radius, int color) {
        super(context);
        mContext = context;
        if (radius > MAX_RADIUS) {
            mSampling = radius / 25.0f;
            mRadius = MAX_RADIUS;
        } else {
            mRadius = radius;
        }
        mColor = color;
    }

    /**
     * @param context Context
     * @param radius  The blur's radius.
     */
    public FastBlur(Context context, @FloatRange(from = 0.0f) float radius) {
        this(context, radius, Color.TRANSPARENT);
    }

    public FastBlur(Context context) {
        this(context, DEFAULT_RADIUS);
    }

    /**
     * Transforms the given {@link Bitmap} based on the given dimensions and returns the transformed
     * result.
     * <p/>
     * <p>
     * The provided Bitmap, toTransform, should not be recycled or returned to the pool. Glide will automatically
     * recycle and/or reuse toTransform if the transformation returns a different Bitmap. Similarly implementations
     * should never recycle or return Bitmaps that are returned as the result of this method. Recycling or returning
     * the provided and/or the returned Bitmap to the pool will lead to a variety of runtime exceptions and drawing
     * errors. See #408 for an example. If the implementation obtains and discards intermediate Bitmaps, they may
     * safely be returned to the BitmapPool and/or recycled.
     * </p>
     * <p/>
     * <p>
     * outWidth and outHeight will never be {@link Target#SIZE_ORIGINAL}, this
     * class converts them to be the size of the Bitmap we're going to transform before calling this method.
     * </p>
     *
     * @param pool        A {@link BitmapPool} that can be used to obtain and
     *                    return intermediate {@link Bitmap}s used in this transformation. For every
     *                    {@link Bitmap} obtained from the pool during this transformation, a
     *                    {@link Bitmap} must also be returned.
     * @param toTransform The {@link Bitmap} to transform.
     * @param outWidth    The ideal width of the transformed bitmap (the transformed width does not need to match exactly).
     * @param outHeight   The ideal height of the transformed bitmap (the transformed heightdoes not need to match
     */
    @Override
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        boolean needScaled = mSampling == DEFAULT_SAMPLING;
        int originWidth = toTransform.getWidth();
        int originHeight = toTransform.getHeight();
        int width, height;
        if (needScaled) {
            width = originWidth;
            height = originHeight;
        } else {
            width = (int) (originWidth / mSampling);
            height = (int) (originHeight / mSampling);
        }
        //find a re-use bitmap
        Bitmap bitmap = pool.get(width, height, Bitmap.Config.ARGB_8888);
        if (bitmap == null) {
            bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        }

        Canvas canvas = new Canvas(bitmap);
        if (mSampling != DEFAULT_SAMPLING) {
            canvas.scale(1 / mSampling, 1 / mSampling);
        }
        Paint paint = new Paint();
        paint.setFlags(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG);
        PorterDuffColorFilter filter =
                new PorterDuffColorFilter(mColor, PorterDuff.Mode.SRC_ATOP);
        paint.setColorFilter(filter);
        canvas.drawBitmap(toTransform, 0, 0, paint);
// TIPS: Glide will take care of returning our original Bitmap to the BitmapPool for us,
// we needn't to recycle it.
//        toTransform.recycle();  <--- Just for tips. by Ligboy

        RenderScript rs = RenderScript.create(mContext);
        Allocation input = Allocation.createFromBitmap(rs, bitmap, Allocation.MipmapControl.MIPMAP_NONE,
                Allocation.USAGE_SCRIPT);
        Allocation output = Allocation.createTyped(rs, input.getType());
        ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));

        blur.setInput(input);
        blur.setRadius(mRadius);
        blur.forEach(output);
        output.copyTo(bitmap);

        rs.destroy();

        if (needScaled) {
            return bitmap;
        } else {
            Bitmap scaled = Bitmap.createScaledBitmap(bitmap, originWidth, originHeight, true);
            bitmap.recycle();
            return scaled;
        }
    }

    /**
     * A method to get a unique identifier for this particular transformation that can be used as part of a cache key.
     * The fully qualified class name for this class is appropriate if written out, but getClass().getName() is not
     * because the name may be changed by proguard.
     * <p/>
     * <p>
     * If this transformation does not affect the data that will be stored in cache, returning an empty string here
     * is acceptable.
     * </p>
     *
     * @return A string that uniquely identifies this transformation.
     */
    @Override
    public String getId() {
        StringBuilder sb = new StringBuilder(ID);
        sb
                .append('-').append(mRadius)
                .append('-').append(mColor);
        return sb.toString();
    }

}
第二种方法只要sdk版本大于17就可行用法也是一样
Glide.with(this).load(url).asBitmap().transform(new FastBlur(this, 25)).into(ivbg);

minSdkVersion 17

效果如图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android实现高斯模糊效果有多种方式。一种常用的方式是使用Glide库来加载图片并应用高斯模糊转换。通过使用`bitmapTransform`方法和`BlurTransformation`类,可以将图片进行高斯模糊处理。例如,可以使用以下代码实现高斯模糊效果: ```java Glide.with(this) .load(R.mipmap.image) .apply(bitmapTransform(new BlurTransformation(100))) .into(blurIv); ``` 另一种方式是通过手势滑动来实现动态的高斯模糊效果。可以通过监听触摸事件,在滑动过程中改变模糊图片的alpha值来达到不同程度的模糊效果。例如,可以使用以下代码实现: ```java mBlurImage.setOnTouchListener(new OnTouchListener() { private float mLastY; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mLastY = event.getY(); break; case MotionEvent.ACTION_MOVE: float y = event.getY(); float alphaDelt = (y - mLastY) / 1000; float alpha = mBlurImage.getAlpha() + alphaDelt; if (alpha > 1.0) { alpha = 1.0f; } else if (alpha < 0.0) { alpha = 0.0f; } mTextView.setText(String.valueOf(alpha)); mBlurImage.setAlpha(alpha); break; case MotionEvent.ACTION_UP: break; } return true; } }); ``` 总结来说,Android实现高斯模糊效果可以使用Glide库进行静态处理,也可以通过手势滑动来实现动态效果。具体选择哪种方式取决于实际需求和开发者的偏好。\[2\]\[3\] #### 引用[.reference_title] - *1* [Android12 支持高斯模糊高斯模糊原理](https://blog.csdn.net/u012165769/article/details/120888709)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [android高斯模糊](https://blog.csdn.net/u014709812/article/details/51564856)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Android多种方式实现高斯模糊效果](https://blog.csdn.net/u012556114/article/details/81871578)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值