Glide变换功能

168 阅读2分钟

源码分析

  • 重点关注transform()方法。
public class CenterCrop extends BitmapTransformation {

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

    public CenterCrop(BitmapPool bitmapPool) {
        super(bitmapPool);
    }

    // Bitmap doesn't implement equals, so == and .equals are equivalent here.
    @SuppressWarnings("PMD.CompareObjectsWithEquals")
    @Override
    
    /**
     * 
     * @param pool 这个是Glide中的一个Bitmap缓存池,用于对Bitmap对象进行重用,否则每次图片变换都重新创建Bitmap对象将会非常消耗内存。
     * @param toTransform 原始Bitmap
     * @param outWidth 变换后的宽
     * @param outHeight 变换后的高
     * @return
     */
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        final Bitmap toReuse = pool.get(outWidth, outHeight, toTransform.getConfig() != null
                ? toTransform.getConfig() : Bitmap.Config.ARGB_8888);
        Bitmap transformed = TransformationUtils.centerCrop(toReuse, toTransform, outWidth, outHeight);
        if (toReuse != null && toReuse != transformed && !pool.put(toReuse)) {
            toReuse.recycle();
        }
        return transformed;
    }

    @Override
    public String getId() {
        return "CenterCrop.com.bumptech.glide.load.resource.bitmap";
    }
}
public final class TransformationUtils {
    ...

    public static Bitmap centerCrop(Bitmap recycled, Bitmap toCrop, int width, int height) {
        //(1)如果原图为空,或者原图的尺寸和目标裁剪尺寸相同,那么就放弃裁剪。
        if (toCrop == null) {
            return null;
        } else if (toCrop.getWidth() == width && toCrop.getHeight() == height) {
            return toCrop;
        }
        // From ImageView/Bitmap.createScaledBitmap.
        //(2)数学计算
        final float scale;
        float dx = 0, dy = 0;
        Matrix m = new Matrix();
        if (toCrop.getWidth() * height > width * toCrop.getHeight()) {
            scale = (float) height / (float) toCrop.getHeight();
            dx = (width - toCrop.getWidth() * scale) * 0.5f;
        } else {
            scale = (float) width / (float) toCrop.getWidth();
            dy = (height - toCrop.getHeight() * scale) * 0.5f;
        }
        m.setScale(scale, scale);
        m.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));

        //(3)判断缓存池中取出的Bitmap对象是否为空,如果不为空就可以直接使用,如果为空则要创建一个新的Bitmap对象。
        final Bitmap result;
        if (recycled != null) {
            result = recycled;
        } else {
            result = Bitmap.createBitmap(width, height, getSafeConfig(toCrop));
        }

        // We don't add or remove alpha, so keep the alpha setting of the Bitmap we were given.
        //(4)将原图Bitmap对象的alpha值复制到裁剪Bitmap对象上面
        TransformationUtils.setAlpha(toCrop, result);
        //(5)Bitmap对象进行绘制
        Canvas canvas = new Canvas(result);
        Paint paint = new Paint(PAINT_FLAGS);
        canvas.drawBitmap(toCrop, m, paint);
        return result;
    }

    ...
}

总结:

  • 如果原图为空,或者原图的尺寸和目标裁剪尺寸相同,那么就放弃裁剪。
  • 数学计算。
  • 判断缓存池中取出的Bitmap对象是否为空,如果不为空就可以直接使用,如果为空则要创建一个新的Bitmap对象。
  • 将原图Bitmap对象的alpha值复制到裁剪Bitmap对象上面。
  • Bitmap对象进行绘制。

参考: