以Glide為例:
Glide.with(getContext()).load(item.getSoftLogo()).transform(this.glideRoundTransform).into(vh.ivSoftIcon);
Glide 提供了transform()方法。
/** * Transform {@link GlideDrawable}s using the given * {@link com.bumptech.glide.load.resource.bitmap.BitmapTransformation}s. * * <p> * Note - Bitmap transformations will apply individually to each frame of animated GIF images and also to * individual {@link Bitmap}s. * </p> * * @see #centerCrop() * @see #fitCenter() * @see #bitmapTransform(com.bumptech.glide.load.Transformation[]) * @see #transform(com.bumptech.glide.load.Transformation[]) * * @param transformations The transformations to apply in order. * @return This request builder. */ public DrawableRequestBuilder<ModelType> transform(BitmapTransformation... transformations) { return bitmapTransform(transformations); }
此方法接受 BitmapTransformation 類形參數。

import android.content.Context; import android.graphics.Bitmap; import com.bumptech.glide.Glide; import com.bumptech.glide.load.Transformation; import com.bumptech.glide.load.engine.Resource; import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; import com.bumptech.glide.request.target.Target; import com.bumptech.glide.util.Util; /** * A simple {@link com.bumptech.glide.load.Transformation} for transforming {@link android.graphics.Bitmap}s that * abstracts away dealing with {@link com.bumptech.glide.load.engine.Resource} objects for subclasses. * * Use cases will look something like this: * <pre> * <code> * public class FillSpace extends BaseBitmapTransformation { * {@literal @Override} * public Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) { * if (toTransform.getWidth() == outWidth && toTransform.getHeight() == outHeight) { * return toTransform; * } * * return Bitmap.createScaledBitmap(toTransform, outWidth, outHeight, true); * } * } * </code> * </pre> */ public abstract class BitmapTransformation implements Transformation<Bitmap> { private BitmapPool bitmapPool; public BitmapTransformation(Context context) { this(Glide.get(context).getBitmapPool()); } public BitmapTransformation(BitmapPool bitmapPool) { this.bitmapPool = bitmapPool; } @Override public final Resource<Bitmap> transform(Resource<Bitmap> resource, int outWidth, int outHeight) { if (!Util.isValidDimensions(outWidth, outHeight)) { throw new IllegalArgumentException("Cannot apply transformation on width: " + outWidth + " or height: " + outHeight + " less than or equal to zero and not Target.SIZE_ORIGINAL"); } Bitmap toTransform = resource.get(); int targetWidth = outWidth == Target.SIZE_ORIGINAL ? toTransform.getWidth() : outWidth; int targetHeight = outHeight == Target.SIZE_ORIGINAL ? toTransform.getHeight() : outHeight; Bitmap transformed = transform(bitmapPool, toTransform, targetWidth, targetHeight); final Resource<Bitmap> result; if (toTransform.equals(transformed)) { result = resource; } else { result = BitmapResource.obtain(transformed, bitmapPool); } return result; } /** * Transforms the given {@link android.graphics.Bitmap} based on the given dimensions and returns the transformed * result. * * <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> * outWidth and outHeight will never be {@link com.bumptech.glide.request.target.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 com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool} that can be used to obtain and * return intermediate {@link Bitmap}s used in this transformation. For every * {@link android.graphics.Bitmap} obtained from the pool during this transformation, a * {@link android.graphics.Bitmap} must also be returned. * @param toTransform The {@link android.graphics.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 * exactly). */ protected abstract Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight); }
BitmapTransformation 虛擬方法
protected abstract Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight);
意思通過此方法轉換和處理圖片,並返回給Glide一個bitmap.此bitmap Glide也將替你管理。
剩下的只要你去做處理了。
下面做一個圖角的處理
通過重寫paint繪制疊加的效果來處理。
關鍵代碼如下:
/** * @param pool * @param source * @return */ private static Bitmap roundCrop(BitmapPool pool, Bitmap source) { if (source == null) return null; //獲取一張位圖用來往上面繪制 Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); if (result == null) { result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); } //使用獲取的位圖新建一張畫布 Canvas canvas = new Canvas(result); //新建一個畫筆 Paint paint = new Paint(); paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP)); paint.setAntiAlias(true); RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight()); canvas.drawRoundRect(rectF, radius, radius, paint); //先畫圖片,再畫圓角矩形,獲取交集 return result; }
BitmapShader
public BitmapShader(Bitmap bitmap,Shader.TileMode tileX,Shader.TileMode tileY) 調用這個方法來產生一個畫有一個位圖的渲染器(Shader)。 bitmap 在渲染器內使用的位圖 tileX The tiling mode for x to draw the bitmap in. 在位圖上X方向花磚模式 tileY The tiling mode for y to draw the bitmap in. 在位圖上Y方向花磚模式 TileMode:(一共有三種) CLAMP :如果渲染器超出原始邊界范圍,會復制范圍內邊緣染色。 REPEAT :橫向和縱向的重復渲染器圖片,平鋪。 MIRROR :橫向和縱向的重復渲染器圖片,這個和REPEAT 重復方式不一樣,他是以鏡像方式平鋪。
處理成黑白 代碼如下:
1 int w = source.getWidth(); 2 int h = source.getHeight(); 3 4 Bitmap resultBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565); 5 int color = 0; 6 int a,r,g,b,r1,g1,b1; 7 int[] oldPx = new int[w * h]; 8 int[] newPx = new int[w * h]; 9 10 source.getPixels(oldPx, 0, w, 0, 0, w, h); 11 for(int i = 0; i < w * h; i++){ 12 color = oldPx[i]; 13 14 r = Color.red(color); 15 g = Color.green(color); 16 b = Color.blue(color); 17 a = Color.alpha(color); 18 19 //黑白矩陣 20 r1 = (int) (0.33 * r + 0.59 * g + 0.11 * b); 21 g1 = (int) (0.33 * r + 0.59 * g + 0.11 * b); 22 b1 = (int) (0.33 * r + 0.59 * g + 0.11 * b); 23 24 //檢查各像素值是否超出范圍 25 if(r1 > 255){ 26 r1 = 255; 27 } 28 29 if(g1 > 255){ 30 g1 = 255; 31 } 32 33 if(b1 > 255){ 34 b1 = 255; 35 } 36 37 newPx[i] = Color.argb(a, r1, g1, b1); 38 } 39 resultBitmap.setPixels(newPx, 0, w, 0, 0, w, h); 40 return resultBitmap;
效果如下:
同理可以加其它濾鏡、水印等。