Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception: Transformation rounded returned input Bitmap but recycled it #997

Closed
cnordvik opened this issue Apr 26, 2015 · 5 comments
Closed

Comments

@cnordvik
Copy link

I get this error on a rounded transformation on one of our users profile picture. Any idea on how to handle this properly?

The images that causes all the issues is this one:
https://graph.facebook.com/675276189284495/picture?type=large

We have hundreds of others and none of them make the transformation crash except this FB profile image.

E/AndroidRuntime(14239): java.lang.IllegalStateException: Transformation rounded returned input Bitmap but recycled it.
E/AndroidRuntime(14239):    at com.squareup.picasso.BitmapHunter$5.run(BitmapHunter.java:462)
E/AndroidRuntime(14239):    at android.os.Handler.handleCallback(Handler.java:739)
E/AndroidRuntime(14239):    at android.os.Handler.dispatchMessage(Handler.java:95)

Here is some of the code for the transformation:

@Override
public Bitmap transform(final Bitmap source) {
    try {
        int size = Math.min(source.getWidth(), source.getHeight());

        int x = (source.getWidth() - size) / 2;
        int y = (source.getHeight() - size) / 2;

        Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
        if (squaredBitmap != source) {
            source.recycle();
        }

        Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());

        Canvas canvas = new Canvas(bitmap);

        Paint paint = new Paint();

        BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
        paint.setShader(shader);
        paint.setAntiAlias(true);

        Mode mMode = Mode.DST_OVER;
        paint.setColorFilter(new PorterDuffColorFilter(Color.argb(255, 255, 255, 255), mMode));

        float r = size/2f;
        canvas.drawCircle(r, r, r, paint);

        squaredBitmap.recycle();
        return bitmap;
    }
    catch(Exception ex)
    {
        return source;
    }


}
@f2prateek
Copy link
Contributor

tl;dr: You returned a bitmap that was already recycled.

I'm guessing that your code goes down the if (squaredBitmap != source) { source.recycle(); } path and recycles the source bitmap. There's a quite a bit that happens after that line, and this part can throw an exception. Since you catch this exception and end up returning source anyway (which is already recycled), Picasso complains about it.

Remove the catch(Exception ex) block and you shouldn't have this issue.

@cnordvik
Copy link
Author

I removed that and it crashed with:
Caused by: java.lang.NullPointerException: Attempt to read from field 'int android.graphics.Bitmap$Config.nativeInt' on a null object reference
app.util.RoundedTransformationGlide.transform(RoundedTransformationGlide.java:29)

which is the same as the one who wrote this comment (he is using Glide but still seems like the same issue):
http://stackoverflow.com/questions/27394016/how-does-one-use-glide-to-download-an-image-into-a-bitmap#comment43272651_27394484

and he has a gif, same as me. So doesn't this transformation work with GIFs?

@JakeWharton
Copy link
Collaborator

If it does not then it's an Android bug. The cause of the original problem was identified (returning a recycled bitmap in your catch block) and the rest of the code looks good as far as the transformation goes. For further problems you'll have better luck elsewhere (such as StackOverflow) as it's not a problem with Picasso specifically.

@heitorcolangelo
Copy link

The problem is when Android performs this operation in your transform class:

Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig()); 

If the image is a GIF, the getConfig() method returns null.
Add this line berfore the first mentioned:

Bitmap.Config config = source.getConfig() != null ? source.getConfig() : Bitmap.Config.ARGB_8888;

and then change the last parameter to config, like this:

Bitmap bitmap = Bitmap.createBitmap(size, size, config);

The final code should be like:

// For gif images
Bitmap.Config config = source.getConfig() != null ? source.getConfig() : Bitmap.Config.ARGB_8888;
Bitmap bitmap = Bitmap.createBitmap(size, size, config); 

Reference: comment of alxscms in this link
https://gist.github.com/julianshen/5829333

@crysxd
Copy link

crysxd commented Dec 5, 2020

A little unrelated but this discussion was the first hit in Google for my issue. Maybe it helps someone :) My app crashed with the same error, the reason was that I used

val result = Bitmap.createBitmap(
     source,
     minX,
     minY,
     maxX - minX + 1,
     maxY - minY + 1
 )
 source.recycle()

but if the dimensions of the created Bitmap where identical to source, createBitmap returns source which then got recycled. The documentation of createBitmap says The new bitmap may be the same object as source, or a copy may have been made. Solution:

if (source != result) {
    source.recycle()
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants