Reputation: 6881
I am fetching images using Picasso and running them through a Transformation. Weird thing is that although the Transformation object is created for each image, the method transform is only called once.
I create a number of the following objects (parsed using Gson) and then invoke "postDeserialise" on them.
@Hide
transient public ObservableField<Drawable> badgeImage;
@Hide
transient private ImageUtils.ImageTarget bindableFieldTarget;
public void postDeserialise(Context context, String src){
if (imageURL != null) {
badgeImage = new ObservableField<Drawable>();
bindableFieldTarget = new ImageUtils.ImageTarget(badgeImage, context.getResources());
if (progress.compareTo(BigDecimal.ONE)==0) {
Picasso.with(context)
.load(imageURL)
.into(bindableFieldTarget);
}
else {
GrayscaleTransformation transform = new GrayscaleTransformation(Picasso.with(context), progress);
Picasso.with(context)
.load(imageURL)
.transform(transform)
.into(bindableFieldTarget);
}
}
}
The following is the GrayscaleTransformation class:
private static final String TAG = "GrayscaleTransformation";
private final Picasso picasso;
private BigDecimal percentageToTransform;
public GrayscaleTransformation(Picasso picasso, BigDecimal percentageToTransform) {
this.picasso = picasso;
this.percentageToTransform = percentageToTransform;
Log.d(TAG, "New GrayscaleTransformation percentageToTransform = " + percentageToTransform);
}
@Override public Bitmap transform(Bitmap source) {
Log.d(TAG, "transform ....");
Bitmap result = createBitmap(source.getWidth(), source.getHeight(), source.getConfig());
Bitmap noise;
try {
noise = picasso.load(R.drawable.noise).get();
} catch (IOException e) {
throw new RuntimeException("Failed to apply transformation! Missing resource.");
}
BitmapShader shader = new BitmapShader(noise, REPEAT, REPEAT);
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.setSaturation(0);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);
Paint paint = new Paint(ANTI_ALIAS_FLAG);
paint.setColorFilter(filter);
Canvas canvas = new Canvas(result);
int width = canvas.getWidth();
int clipPoint = percentageToTransform.multiply(new BigDecimal(width)).intValue();
Log.d(TAG, "width/clipPoint = " + width + "/" + clipPoint);
canvas.clipRect(clipPoint, 0, canvas.getWidth(), canvas.getHeight(), Region.Op.REPLACE);
canvas.drawBitmap(source, 0, 0, paint);
paint.setColorFilter(null);
paint.setShader(shader);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
canvas.drawRect(0, 0, width, canvas.getHeight(), paint);
canvas.clipRect(0, 0, clipPoint, canvas.getHeight(), Region.Op.REPLACE);
canvas.drawBitmap(source, 0, 0, new Paint());
source.recycle();
noise.recycle();
return result;
}
@Override public String key() {
return "grayscaleTransformation()";
}
And the "target"
public static class ImageTarget implements Target {
private ObservableField<Drawable> observableField;
private Resources resources;
public ImageTarget(ObservableField<Drawable> observableField, Resources resources) {
this.observableField = observableField;
this.resources = resources;
}
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
observableField.set(new BitmapDrawable(resources, bitmap));
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
observableField.set(errorDrawable);
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
observableField.set(placeHolderDrawable);
}
}
The transformation class is definitely created each time as I see it in the log but the transform method is only invoked once.
Upvotes: 0
Views: 366
Reputation: 8574
Picasso
is loading the images from the its in-memory cache.
That will return to the Target
immediately with the already cached result, no need to call transform
on the Transformation
.
If you want a Tranformation
to change the cache key, simply change the implementation of key()
.
Also, note that you should implement the equals and hashcode contract on all Target
s.
Upvotes: 1