原文:Custom Transformation
作者:Norman Peitek
翻译:Dexter0218
前面的12篇文章中,你已经学会了所有的基础请求去实现Glide的标准功能。从这篇文章开始,我们将要深入研究一些高级话题。这篇文章进一步研究变换(Transformations)。
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
在图片显示出之前可以对图片进行变换处理。例如,如果你的app需要显示一张灰度图,但只能获取到一个原始全色彩的版本,你可以使用一个变换去将图片从有明艳色彩的版本转换成惨淡的黑白版。不要误会我们,变换不仅限于颜色。你可以改变图片的很多属性:大小、边框、色彩、像素点,等等!在之前介绍用Glide调整图片大小时,已经介绍了自带的两个变换fitCenter
和 centerCrop
。这两个方案都有一个显著的特征,他们有他们自己的Glide转换方法,所以,这篇文章不再介绍了。
为了实现你自己自定义的变换,你需要创建一个新的类去实现变换接口。这个方法需要实现的内容还是相当复杂的,你需要深入探索Glide的内部结构才能让其工作好。如果你只是想要常规的图片(不包括Gif和视频)变换,我们建议只要处理抽象的BitmapTransformation
类。它简化了相当多的实现,能覆盖95%的使用范围。
所以,让我们先看一下BitmapTransformation
实现的一个例子。如果你有规律地看我们的文章,你知道我们最喜欢的变换是用Renderscript
去模糊图片。我们可以用之前用过的代码去实现一个Glide变换。我们的框架必须继承BitmapTransformation
类:
public class BlurTransformation extends BitmapTransformation {
public BlurTransformation(Context context) {
super( context );
}
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
return null; // todo
}
@Override
public String getId() {
return null; // todo
}
}
现在,我们用前面文章的代码,借助Renderscript
来实现图片的模糊处理。
public class BlurTransformation extends BitmapTransformation {
private RenderScript rs;
public BlurTransformation(Context context) {
super( context );
rs = RenderScript.create( context );
}
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
Bitmap blurredBitmap = toTransform.copy( Bitmap.Config.ARGB_8888, true );
// Allocate memory for Renderscript to work with
Allocation input = Allocation.createFromBitmap(
rs,
blurredBitmap,
Allocation.MipmapControl.MIPMAP_FULL,
Allocation.USAGE_SHARED
);
Allocation output = Allocation.createTyped(rs, input.getType());
// Load up an instance of the specific script that we want to use.
ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
script.setInput(input);
// Set the blur radius
script.setRadius(10);
// Start the ScriptIntrinisicBlur
script.forEach(output);
// Copy the output to the blurred bitmap
output.copyTo(blurredBitmap);
toTransform.recycle();
return blurredBitmap;
}
@Override
public String getId() {
return "blur";
}
}
再次提醒,如果你对transform()
里的代码困惑,建议看看之前的文章。getId()
方法为这个变换描述了一个独有的识别。Glide使用那个关键字作为缓存系统的一部分。防止出现异常问题,确保其唯一。
下一节,我们要学习如何应用我们创建的变换方法。
Glide has two ways of applying a transformation. The first is to pass an instance of your class as a parameter to .transform(). You can apply any transformation there, no matter if it's for an image or Gif. The other option is to use .bitmapTransform(), which only accepts transformations for bitmaps. Since our implementation above is designed for bitmaps, we could use either one:
Glide有两个不同的方式进行变换。第一个是传递一个你的类的实例作为.transform()
的参数。不管是图片还是gif,都可以进行变换。另一个则是使用.bitmapTransform()
,它只接受bitmap的变换。由于我们的实现都是基于bitmap,我们可以使用第一个:
Glide
.with( context )
.load( eatFoodyImages[0] )
.transform( new BlurTransformation( context ) )
//.bitmapTransform( new BlurTransformation( context ) ) // this would work too!
.into( imageView1 );
这足够让Glide从网络下载的图片自动实现模糊算法。非常有用!
通常,Glide的流接口(fluent interface)允许方法被连接在一起,然而变换并不是这样的。确保你只调用.transform()
或者.bitmapTransform()
一次,不然,之前的设置将会被覆盖!然而,你可以通过传递多个转换对象当作参数到.transform()
(或者.bitmapTransform()
)中来进行多重变换:
Glide
.with( context )
.load( eatFoodyImages[1] )
.transform( new GreyscaleTransformation( context ), new BlurTransformation( context ) )
.into( imageView2 );
在这段代码中,我们先对图片进行了灰度变换,然后模糊处理。Glide会为你自动进行两个转换。牛逼吧!
提示:当你使用变换的时候,你不能使用.centerCrop()
或者.fitCenter()
。
如果你已经对你的app里要用什么变换有了想法,在花点时间看看下面的库吧:Glide-transformations。它提供了许多变换的集合。值得去看一下你的idea是否已经被实现了。
这个库有2个不同版本。扩展库包括更多的变换,并且是用手机的GPU进行计算。需要一个额外的依赖,所以这两个版本的设置还有点不一样。你应当看看支持的变换的列表,再决定你需要用哪个版本。
设置是很简单的!对于基本版,你可以在你的build.gradle里加一行:
dependencies {
compile 'jp.wasabeef:glide-transformations:2.0.0'
}
如果你想要使用GPU变换:
repositories {
jcenter()
mavenCentral()
}
dependencies {
compile 'jp.wasabeef:glide-transformations:2.0.0'
compile 'jp.co.cyberagent.android.gpuimage:gpuimage-library:1.3.0'
}
在你同步了Android Studio的builde.gradle文件后,你已经可以进行使用变换集合了。使用方式与使用自定义变换一样。假如我们要用glide变换集合去模糊图片:
Glide
.with( context )
.load( eatFoodyImages[2] )
.bitmapTransform( new jp.wasabeef.glide.transformations.BlurTransformation( context, 25 ) )
.into( imageView3 );
你也可以像上面一样应用一组变换。一个单独的变换或者一组变换,.bitmapTransform()
都可以接受!
这边文章中,你已经学会了Glide的一个非常有用的工具:变换。你已经知道如何实现并应用预定义的变换,我们希望这提供给你应用到app里所有需要的帮助!如果你有问题,在评论区提出!
这篇文件讲解了一个非常定制化的特征,后面的文章将介绍另一个:自定义动画。