theblitz
theblitz

Reputation: 6881

Picasso only calling transform once

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

Answers (1)

Eric Cochran
Eric Cochran

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 Targets.

Upvotes: 1

Related Questions