Glide 之 自定义 Transformations

   不了解Glide的童鞋,可以先前往官网https://github.com/bumptech/glide,或者https://mrfu.me/2016/02/27/Glide_Getting_Started/ 从头开始学习,一步一步了解Glide的各个API的使用。
   这里,我只针对近期在做项目的时候遇到要针对原始Bitmap进行转换(变换后)再次显示在ListView 或者Grid上面。
   Glide的一般使用只要传入对用的图片或者媒体资源的url地址,Glide就会针对将要显示的控件View(如ImageView)自动压缩变换生成合适尺寸和大小的Bitmap,如果需求发生改变,如:只需要显示图片的某一部分,或者给图片加上特效等等,我们就需要用到Glide的图形转换器:Transformation。你可以用 transformation 去操作 bitmap,从而将一个明亮色彩版本的图片转换成灰暗的版本。不要理解错啦,transformation 不仅限于颜色转换。你可以图片的任意属性:尺寸,范围,颜色,像素位置等等!Glide 已经包含了2个 transformation,即:fitCenter 和 centerCrop。这两个选项都非常有意义,他们在 Glide 中拥有自己的实现。当然,我们这里要实现你自己的 Transformation。
   为了实践自定义转换,你将需要创建一个新类,它实现了 Transformation 接口。要实现这个方法还是比较复杂的,你必须要有对 Glide 内部架构方面的洞察力才能做的比较棒。如果你只是想要对图片(不是 Gif 和 video)做常规的 bitmap 转换,我推荐你使用抽象类 BitmapTransformation。它简化了很多的实现,这应该能覆盖 95% 的应用场景啦。来看看 BitmapTransformation 实现实例。我们继承 BitmapTransformation 类。
    public class GridBitmapTransformation extends BitmapTransformation {

    public BlurTransformation(Context context) {
        super( context );
    }

    @Override
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        //pool: Bitmap缓存池,你可以从中取出你想要复用的Bitmap进行复用,防止重复创建带来的内存消耗。
        //toTransform:Glide根据你的View控件压缩后将要现实的Bitmap(也就是经过Glide压缩后的图片)。
        //outWidth:将要显示的View的宽,outHeight将要现实的高

        //在该方法中你主要针对toTransform 进行变换

        return null; // todo
    }

    @Override
    public String getId() {
        return null; // todo
    }
}

说明:transform 主要用做Bitmap变换的重写,getId 方法描述了这个转换的唯一标识符,Glide 使用该键作为缓存系统的一部分,为了避免意外的问题,你要确保它是唯一的。

下面看下我自己的转换器:

/**
 * Description:GridList page image crop converter, generate 1: 1 square 90 degree Bitmap.
 * Author: Created by lixby .
 */

public class GridBitmapTransformation extends BitmapTransformation {

    private static final String TAG="GridTransformation";

    /**Picture horizontal degree*/
    private static final int H_DEGREE=360;
    /**Picture vertical degree*/
    private static final int V_DEGREE=180;
    /**Horizontal cropping degree*/
    private static final int H_CROPPING_DEGREE=90;
    /**vertical cropping degree*/
    private static final int V_CROPPING_DEGREE=90;


    private static final String TRANSFORMATION_ID="GridBitmapTransformation";

    public GridBitmapTransformation(Context context) {
        super(context);
    }

    @Override
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        if (toTransform == null) {
            return null;
        } else if (toTransform.getWidth() == outWidth && toTransform.getHeight() == outHeight) {
            return toTransform;
        }
        //取出压缩后Bitmap的宽高:注意,压缩后其实只改变了图片的质量(分辨率降低之类),但是图片的尺寸并没有发生变换,之前是什么图,压缩后还是那张图,改变的只是突变质量。

        int inWidth=toTransform.getWidth();
        int inHeight=toTransform.getHeight();

        //根据自己的需求进行Bitmap变化。
        int x=((inWidth*(H_DEGREE-H_CROPPING_DEGREE))/H_DEGREE)/2;
        int y=((inHeight*(V_DEGREE-V_CROPPING_DEGREE))/V_DEGREE)/2;

        int width=inWidth*H_CROPPING_DEGREE/H_DEGREE;
        int height=inHeight*V_CROPPING_DEGREE/V_DEGREE;

        Bitmap centerBitMap=Bitmap.createBitmap(toTransform,x,y,width,height);

        //这里做下主要说明:BitmapPool ,当你在这个方法返回变换后的Bitmap后,Glide会自动帮你将其存入BitmapPool,不需要你去主动添加。而这里是根据你变换后的Bitmap宽高取出对用缓存的Bitmap,可以复用,如果没有就根据你变换要求的Bitmap重新创建一个新的返回就可以了。

        Bitmap result = pool.get(centerBitMap.getWidth(), centerBitMap.getHeight(), Bitmap.Config.ARGB_8888);
        if(result==null){
            result = Bitmap.createBitmap(centerBitMap.getWidth(), centerBitMap.getHeight(), Bitmap.Config.ARGB_8888);
        }


        //Place the bitmap in the drawing area and draw the picture to be stitched into the specified memory area
        Canvas canvas = new Canvas(result);
        canvas.drawBitmap(centerBitMap, 0, 0, null);

        //Recycle unused BitMap
        centerBitMap.recycle();

        return result;
    }

    @Override
    public String getId() {

        // Return some id that uniquely identifies your transformation.
        return TRANSFORMATION_ID;
    }

}

上面的案例我写了对用的注释应该不难了理解,强调一点:toTransform 并不需要你去主动回收,GLide会帮助你来回收。

自定义转换器使用:

Glide.with(context).load("url")
                .transform(new GridBitmapTransformation(context))
                .into(imgItem);

也可以添加多个变化:

Glide.with(context).load("url")
                .transform(new GridBitmapTransformation(context),......)
                .into(imgItem);

另外:你也可以加入另一个transformations 库,https://github.com/wasabeef/glide-transformations, 里面有很多做好的图形转换,你可以根据自己的需求选择。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章