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, 裏面有很多做好的圖形轉換,你可以根據自己的需求選擇。

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