Android-图片框架之Glide实现图片添加水印,模糊及其他效果以及实现分析

先上代码:

    
                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,你都有三个方法你 必须 实现它们,以使得磁盘和内存缓存正确地工作:

  1. equals()
  2. hashCode()
  3. 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


猜你喜欢

转载自blog.csdn.net/yang1349day/article/details/80327872