当前位置 博文首页 > 文章内容

    Glide框架高斯模糊图片处理:Dijkstra的专栏

    作者:shunshunshun18 栏目:未分类 时间:2021-10-17 20:45:44

    本站于2023年9月4日。收到“大连君*****咨询有限公司”通知
    说我们IIS7站长博客,有一篇博文用了他们的图片。
    要求我们给他们一张图片6000元。要不然法院告我们

    为避免不必要的麻烦,IIS7站长博客,全站内容图片下架、并积极应诉
    博文内容全部不再显示,请需要相关资讯的站长朋友到必应搜索。谢谢!

    另祝:版权碰瓷诈骗团伙,早日弃暗投明。

    相关新闻:借版权之名、行诈骗之实,周某因犯诈骗罪被判处有期徒刑十一年六个月

    叹!百花齐放的时代,渐行渐远!



    推荐 IIS7批量FTP管理工具 IIS7批量FTP管理
    IIS7批量FTP管理功能说明:
    1、可批量导入,导出FTP信息
    2、其他ftp工具有的功能,我们也有
    3、特色功能:可以定时上传下载
    4、数据信息列表化、一眼就能知道那个是那个
    5、批量连接 标签页式切换 方便快捷
    6、7大连接模式 更多好的兼容
    7、内嵌编辑器 有效解决普通txt记事本乱码
    8、锁屏功能 当程序有规定时间内没人操作,则自动锁程序。输入密码才可以正常操作

    本产品适用于:懒得记录FTP信息和有批量定时备份,上传下载的运维或站长。

    图:


    IIS7批量FTP管理

    转自:https://ligboy.org/?p=380

    对于不需要看废话的请直接Show me the code

    对于模糊处理,一般的解决方案有四种:

    1. Java实现的算法处理;
    2. NDK实现的算法处理;
    3. RenderScript处理;
    4. openGL处理;

    这四种方案的性能考虑的话,一般来讲应该是: 1 < 3 < 2  < 4 (2、3的性能非常接近),不过当属RenderScript方式最为简便(很显然嘛,平台无关性)。

    RenderScript是Android自SDK17提供的一套平台无关计算密集脚本,它使用C99语法脚本,可以实现高性能的计算,而其包含大量内联函数,其中就包括了我们今天用到的:ScriptIntrinsicBlur,这是一个高斯模糊处理内联函数,一般系统用来进行阴影的计算处理。

    上面有提到RenderScript是自SDK17引入的,但是Android 团队为我们提供了RenderScript support library,而起在Gradle-base的项目中的引入也极其简单,仅需要在module build.gradle设置以下11、12两行即可:

    android {
        compileSdkVersion 23
        buildToolsVersion "23.0.2"
     
        defaultConfig {
            applicationId "org.ligboy.backsound"
            minSdkVersion 15
            targetSdkVersion 23
            versionCode 1
            versionName "1.0"
            renderscriptTargetApi 20
            renderscriptSupportModeEnabled true
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }

    接下来简单说说 ScriptIntrinsicBlur,使用它虽然很方便,但是也是有弊端的,模糊radius不能超过25.0f,不过我们可以通过缩小原图抽样的方式变相的进行扩大半径。

    Glide是一个优秀的图片加载缓存处理等一系列功能的框架,它优雅而且使用渐变,扩展也很容易,Glide就提供了自定义Transformation的方式进行扩展图片的处理

    到了这里就是通过自定义Transformation的方式,详细的这里就不赘述了,感兴趣可以查看Glide官方文档:Transformation。需要特别提到的是,每个Transformation都有一个String getId()的回调,该ID用于在对处理后的图片进行缓存时的文件命名,这样当下次相同图片使用相同Transformation时,则无需任何实际处理,直接读取缓存文件,所以我们实现时的ID需要同时关联所有的调整参数,参数改变的ID也应该相应改变。下面就是我自定义的BlurTransformation

    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();
        }
    }

    使用起来也是非常简单:

    Glide.with(MainActivity.this).load(imageFile.getUrl())
             .transform(new BlurTransformation(MainActivity.this, 100))
             .crossFade()
             .into(mBackgroundImageView);
    Gist:  https://gist.github.com/ligboy/eee784aa57f40a615179

    cs