玩转Glide 4.x之Transformation变换

写在开头

公司老项目决定从ImageLoader替换为当前流行框架Glide,准备单独开发成图片组件,目前正在学习中,总结一波,希望能和大家共同进步,也希望大家提供更好的封装及思路共同完善这个组件,方便你我的使用。

图片组件地址:https://github.com/loveAndroidAndroid/GlideMoudle(包含图片变换,进度监听,图片(gif)加载等等,还希望大家能一起补充)

PS:也掺杂了一个android权限工具类,包含跳转各个手机型号的权限设置页面。也希望大家提出宝贵的意见。

言归正传:开始今天Transformation变换学习之旅。

Glide推荐学习:https://blog.csdn.net/guolin_blog/article/details/53759439

Transformation用来干什么?

平常开发中,我们时常会对网络加载的图片进行处理,比如Glide自带centerCrop(),fitCenter()处理,自定义圆形,圆角,模糊处理等等。

如何学习Transformation?(基于Glide 4.7.1)

首先我们先学习系统自带的Transformation的做法,然后在自定义自己的Transformation。那么就话不多说,我们直接打开CenterCrop类来看一下它的源码吧,如下所示:

public class CenterCrop extends BitmapTransformation {
  private static final String ID = "com.bumptech.glide.load.resource.bitmap.CenterCrop";
  private static final byte[] ID_BYTES = ID.getBytes(CHARSET);

  //实现图形变换,主要是这个方法
  @Override
  protected Bitmap transform(
      @NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
    return TransformationUtils.centerCrop(pool, toTransform, outWidth, outHeight);
  }
  //重写epquals和hashcode方法,确保对象唯一性,以和其他的图片变换做区分
  @Override
  public boolean equals(Object o) {
    return o instanceof CenterCrop;
  }
  
  @Override
  public int hashCode() {
    return ID.hashCode();
  }
  //可通过内部算法 重写此方法自定义图片缓存key
  @Override
  public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
    messageDigest.update(ID_BYTES);
  }
}
复制代码

第一:CenterCrop继承自BitmapTransformation的,这个是必须的。我们自定义Transformation也要继承这个类。因为整个图片变换功能都是建立在这个继承结构基础上的。

第二:图像变换最重要的就是transform()方法,这个是我们自定义Transformation的关键方法,我们的处理逻辑都要在这个方法里实现。transform()方法中有四个参数。 (1)pool,这个是Glide中的BitmapPool缓存池,用于对Bitmap对象进行重用,否则每次图片变换都重新创建Bitmap对象将会非常消耗内存。

(2)toTransform,这个是原始图片的Bitmap对象,我们就是要对它来进行图片变换。

(3)图片变换后的宽度

(4)图片变换后的高度

我们可以看到transform()的处理都在TransformationUtils中,那么我们看一下transform()方法的细节。源码及解释如下:

public static Bitmap centerCrop(@NonNull BitmapPool pool, @NonNull Bitmap inBitmap, int width,
      int height) {
      //简单校验
    if (inBitmap.getWidth() == width && inBitmap.getHeight() == height) {
      return inBitmap;
    }
    // From ImageView/Bitmap.createScaledBitmap.计算画布的缩放的比例以及偏移值
    final float scale;
    final float dx;
    final float dy;
    Matrix m = new Matrix();
    if (inBitmap.getWidth() * height > width * inBitmap.getHeight()) {
      scale = (float) height / (float) inBitmap.getHeight();
      dx = (width - inBitmap.getWidth() * scale) * 0.5f;
      dy = 0;
    } else {
      scale = (float) width / (float) inBitmap.getWidth();
      dx = 0;
      dy = (height - inBitmap.getHeight() * scale) * 0.5f;
    }

    m.setScale(scale, scale);
    m.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));
    //从Bitmap缓存池中尝试获取一个可重用的Bitmap对象
    Bitmap result = pool.get(width, height, getNonNullConfig(inBitmap));
    // 将原图Bitmap对象的alpha值复制到裁剪Bitmap对象上面
    TransformationUtils.setAlpha(inBitmap, result);
	//裁剪Bitmap对象进行绘制,并将最终的结果进行返回
    applyMatrix(inBitmap, result, m);
    return result;
  }
复制代码

对于equals,hashCode,updateDiskCacheKey不太重要,上面源码中也有相应解释,暂不多说。

自定义Transformation实现圆形图片。

	/**
 * 裁剪图片为圆
 */
public class CircleTransformation extends BitmapTransformation {
    private final String TAG = getClass().getName();

    @Override
    protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
        //得到图片最小边
        int size = Math.min(toTransform.getWidth(), toTransform.getHeight());
        //计算图片起点
        int x = (toTransform.getWidth() - size) / 2;
        int y = (toTransform.getHeight() - size) / 2;
        //创建新的bitmaop
        Bitmap square = Bitmap.createBitmap(toTransform, x, y, size, size);
        //得到glide中BitmapPool的bitmap位图对象
        Bitmap circle = pool.get(size, size, Bitmap.Config.ARGB_8888);

        Canvas canvas = new Canvas(circle);
        Paint paint = new Paint();
        //设置TileMode的样式 CLAMP 拉伸 REPEAT 重复  MIRROR 镜像
        paint.setShader(new BitmapShader(square, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
        paint.setAntiAlias(true);
        float r = size / 2f;
        //画圆
        canvas.drawCircle(r, r, r, paint);
        return circle;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof BlurTransformation) {
            return this == obj;
        }
        return false;
    }

    @Override
    public int hashCode() {
        return Util.hashCode(TAG.hashCode());
    }

    @Override
    public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
        messageDigest.update(TAG.getBytes(CHARSET));
    }
}
复制代码

更多变换

在图片组件中我实现了三种自定义变换,包含圆形,圆角和模糊。

网上也有很多Glide的图片变换开源库,我感觉做的最好的是glide-transformations这个库了吧。它实现了很多通用的图片变换效果,如裁剪变换、颜色变换、模糊变换等等,使得我们可以非常轻松地进行各种各样的图片变换。不过我们用不到那么多功能的话也不需要依赖一个三方库了吧,主要还是要学习为主。

三方库项目地址:https://github.com/wasabeef/glide-transformations

写在最后

今天的文章就到这里了,希望大家也学会了。下篇文章中我会写一下关于关于监听Glide进度的文章,顺一下自己的思路,也记录下自己的学习过程。

你可能感兴趣的:(玩转Glide 4.x之Transformation变换)