先上代码:
if (mBlurTransformation == null) { //模糊处理 mBlurTransformation = new BlurTransformation(14, 3); } GlideApp.with(this) .load(bean.url) .dontAnimate() .override(100, 100) //模糊处理的时候不需要显示太清晰,所以此处限制宽高可以节省内存 .placeholder(R.mipmap.image_icon_def) .error(R.mipmap.image_icon_def) // 设置高斯模糊 //"14":模糊度;"3":图片缩放3倍后再进行模糊,缩放3-5倍个人感觉比较好。 .transform(mBlurTransformation) .into(imageView); if (gifIconTransformation1 == null) { //水印处理 gifIconTransformation1 = new GifIconTransformation3(this, LoginCache.getInstance().getTel()); //根据手机号码去设置水印 } GlideApp.with(this) .load(bean.url) // .transform(new MultiTransformation<Bitmap>( mBlurTransformation ,gifIconTransformation1))//此处可以实现图片的多次转换 .transform(gifIconTransformation1) .placeholder(R.mipmap.image_user_icon_def) .error(R.mipmap.image_user_icon_def) .dontAnimate() .into(imageView);
重要代码:
public class GifIconTransformation2 extends BitmapTransformation { private final String waterStr; private boolean isAddWater = false; private static Paint paint; public GifIconTransformation2(Context context, boolean isAddWater, String waterStr) { super(context); this.isAddWater = isAddWater; this.waterStr = waterStr; } public GifIconTransformation2 setTextSize(float size) { paint.setTextSize(SizeUtils.dp2px(UIUtils.getInstance().getContext(), size)); return this; } public GifIconTransformation2 setAlpha(int alpha) { paint.setAlpha(alpha); return this; } public GifIconTransformation2 isSetWater(boolean isAddWater) { this.isAddWater = isAddWater; return this; } static { paint = new Paint(); paint.setColor(Color.GRAY); //此处为正常像素 // paint.setAlpha(80); // paint.setTextSize(SizeUtils.dp2px(UIUtils.getInstance().getContext(), 10)); paint.setAntiAlias(true); paint.setDither(true); paint.setFilterBitmap(true); } @Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) { if (isAddWater) return addGifIcon(toTransform); else return toTransform; } private Bitmap addGifIcon(Bitmap oldbitmap) { //注意:此处可以根据传递进来的宽和高去调整水印的大小,间距,透明度等.但是实际上在开发过程中,商家上传的图片像素都基本上一致,所以一般不需要设置根据图片大小去设置水印,如果你在开发中确实需要适配不同的像素,请联系我,我写过. int width = oldbitmap.getWidth(); int height = oldbitmap.getHeight(); Canvas canvas = new Canvas(oldbitmap); canvas.save(Canvas.ALL_SAVE_FLAG); canvas.rotate(-30); float textWidth = paint.measureText(waterStr); int index = 0; for (int positionY = height / 12; positionY <= height * 2; positionY += height / 12) { float fromX = -width + (index++ % 2) * textWidth; for (float positionX = fromX; positionX < width; positionX += textWidth * 2) { canvas.drawText(waterStr, positionX, positionY, paint); } } canvas.restore(); return oldbitmap; } @Override public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) { //此处去设置唯一标志符 String s = "包名" + waterStr; try { s.getBytes(STRING_CHARSET_NAME); messageDigest.update(s.getBytes(STRING_CHARSET_NAME)); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } }
public class BlurTransformation extends BitmapTransformation { private static final int VERSION = 1; private static final String ID = "jp.wasabeef.glide.transformations.BlurTransformation." + VERSION; private static final byte[] ID_BYTES = ID.getBytes(CHARSET); private static int MAX_RADIUS = 25; private static int DEFAULT_DOWN_SAMPLING = 1; private int radius; private int sampling; public BlurTransformation() { this(MAX_RADIUS, DEFAULT_DOWN_SAMPLING); } public BlurTransformation(int radius) { this(radius, DEFAULT_DOWN_SAMPLING); } public BlurTransformation(int radius, int sampling) { this.radius = radius; this.sampling = sampling; } @Override protected Bitmap transform(@NonNull Context context, @NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) { int width = toTransform.getWidth(); int height = toTransform.getHeight(); int scaledWidth = width / sampling; int scaledHeight = height / sampling; Bitmap bitmap = pool.get(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); canvas.scale(1 / (float) sampling, 1 / (float) sampling); Paint paint = new Paint(); paint.setFlags(Paint.FILTER_BITMAP_FLAG); canvas.drawBitmap(toTransform, 0, 0, paint); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { try { bitmap = RSBlur.blur(context, bitmap, radius); } catch (RSRuntimeException e) { bitmap = FastBlur.blur(bitmap, radius, true); } } else { bitmap = FastBlur.blur(bitmap, radius, true); } return bitmap; } @Override public String toString() { return "BlurTransformation(radius=" + radius + ", sampling=" + sampling + ")"; } @Override public boolean equals(Object o) { return o instanceof BlurTransformation; } @Override public int hashCode() { return ID.hashCode(); } @Override public void updateDiskCacheKey(MessageDigest messageDigest) { messageDigest.update(ID_BYTES); } }
其实也有开源的框架可以直接依赖使用
implementation 'jp.wasabeef:glide-transformations:3.1.1'
看这个项目的源码,其实和我自己写的水印方式一样一样的,继承然后覆写transform方法.
添加固定位置的水印图片是比较难的,因为ImageView必定是将图片缩放了的,无法固定绘制其位置,建议直接用ImageView去显示即可,不用绘制
后期有时间再去分析其绘制原理.
Glide分析
默认变换
通过 RequestOptions 类可以应用变换:
RequestOptions options = new RequestOptions();
options.centerCrop();
Glide.with(fragment)
.load(url)
.apply(options)
.into(imageView);
大多数内置的变换都有静态的 import ,这是为 API 的流畅性考虑的。例如,你可以通过静态方法应用一个 FitCenter 变换:
import static com.bumptech.glide.request.RequestOptions.fitCenterTransform;
Glide.with(fragment)
.load(url)
.apply(fitCenterTransform())
.into(imageView);
Glide 提供了很多内置的变换,包括:
多重变换
默认情况下,每个 transform()
调用,或任何特定转换方法(fitCenter()
, centerCrop()
, bitmapTransform()
etc)的调用都会替换掉之前的变换。
如果你想在单次加载中应用多个变换,请使用 MultiTransformation
类。
使用 generated API:
Glide.with(fragment)
.load(url)
.transform(new MultiTransformation(new FitCenter(), new YourCustomTransformation())
.into(imageView);
定制变换
也就是文章开头的代码, 如果你只需要变换Bitmap
,最好是从继承
BitmapTransformation
开始。
BitmapTransformation
处理了一些基础的东西,包括提取和回收原始的 Bitmap,如果你的变换返回了一个新修改的 Bitmap 的话。
请特别注意,对于任何 Transformation
子类,包括 BitmapTransformation
,你都有三个方法你 必须 实现它们,以使得磁盘和内存缓存正确地工作:
equals()
hashCode()
updateDiskCacheKey
Glide中的特殊行为
重用变换
Transformation
的设计初衷是无状态的。因此,在多个加载中复用 Transformation
应当总是安全的。创建一次 Transformation
并在多个加载中使用它,通常是很好的实践。
ImageView的自动变换
在Glide中,当你为一个 ImageView 开始加载时,Glide可能会自动应用 FitCenter 或 CenterCrop ,这取决于view的 ScaleType 。由此可以方便的设置圆形头像,但是注意默认的图片不会被设置为圆形的哦,但是你可以使用RoundImageView(github上的开源项目) 去设置圆形的头像.
如果 scaleType
是 CENTER_CROP
, Glide 将会自动应用 CenterCrop
变换。如果 scaleType
为 FIT_CENTER
或 CENTER_INSIDE
,Glide会自动使用 FitCenter
变换。
当然,你总有权利覆写默认的变换,只需要一个带有 Transformation
集合的 RequestOptions 即可。另外,你也可以通过使用 dontTransform()
确保不会自动应用任何变换。
下一篇 Android-图片框架之Glide实现图形验证码及实现分析
参考自Glide中文文档 https://muyangmin.github.io/glide-docs-cn/doc/transformations.html