-
-
Save ryanbateman/6667995 to your computer and use it in GitHub Desktop.
import android.content.Context; | |
import android.graphics.Bitmap; | |
import android.renderscript.Allocation; | |
import android.renderscript.Element; | |
import android.renderscript.RenderScript; | |
import android.renderscript.ScriptIntrinsicBlur; | |
import com.squareup.picasso.Transformation; | |
public class BlurTransform implements Transformation { | |
RenderScript rs; | |
public BlurTransform(Context context) { | |
super(); | |
rs = RenderScript.create(context); | |
} | |
@Override | |
public Bitmap transform(Bitmap bitmap) { | |
// Create another bitmap that will hold the results of the filter. | |
Bitmap blurredBitmap = Bitmap.createBitmap(bitmap); | |
// Allocate memory for Renderscript to work with | |
Allocation input = Allocation.createFromBitmap(rs, bitmap, 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); | |
return blurredBitmap; | |
} | |
@Override | |
public String key() { | |
return "blur"; | |
} | |
} |
Just a note, most methods in ScriptIntrinsicBlur used in this snippet require API level 17.
Thanks, Tad - noted and updated.
Note that if you don't call bitmap.recycle than the following call will fail:
Picasso.with(getActivity())
.load(mClip.getImageUrl(app))
.resize(width, height)
.centerCrop()
.transform(new BlurTransform(getActivity()))
.into(mImageView);
with the following error: "Transformation blur mutated input Bitmap but failed to recycle the original."
So in this case I've re-added the .recycle() call.
Hmm, so I realize that be re-adding the recycle() call my image is not getting cached. So if I don't want to recycle I get the error mentioned above ("Transformation blur mutated input Bitmap but failed to recycle the original.").
Any idea how I can avoid this? Or is there no way to resize and blur an image at the same time?
Quick note: you shouldn't creating a new RS instance in the constructor, which gets called every time - even when the blurred image is being loaded from memory. Instead, store a WeakReference<Context>
and create RenderScript inside of the transform method.
It requires api level 17
Thanks for posting this up.
I had to change one line to get things working in my case:
val blurredBitmap = Bitmap.createBitmap(bitmap)
to
val blurredBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true)
Problem was that BitMap.createBitmap() doesn't always create a copy - sometimes it reuses the bitmap. Looks like this was confusing Picasso's error checking in terms of whether or not the Transformation object correctly handled recycling.
You can make this a LOT faster by setting
Allocation.USAGE_SHARED
and removing thebitmap.recycle()
call.