问题
I am trying to make an application in which the part of the image user touched on the android app gets blurred.
Requirement is like, I should be able to take a snap and then slide over my finger over the points which I need to blur out. Is there any easy way for it. Can I somehow use transparent paint with opacity to accomplish it?
Thanks
回答1:
Seems the issue should be solved using RenderScript. However, seems that it supports only bitmap blur, so we might need to cut bitmap before blurring. Referring to this answer about fast image blur, I was able to achieve surprisingly good performance on Nexus 10 tablet.
The code is following (note: it's draft version, I've played with it only for 30 minutes):
public class BlurTouchImageView extends View {
private static final int BLUR_RADIUS = 20;
// TODO: resources should be used
private static final int BLUR_SIDE = 300;
private RenderScript mBlurScript = null;
private ScriptIntrinsicBlur mIntrinsicScript = null;
private Bitmap mBitmap = null;
private Bitmap mBlurredBitmap = null;
private float mX = -1;
private float mY = -1;
public BlurTouchImageView(final Context context) {
super(context);
init();
}
public BlurTouchImageView(final Context context, final AttributeSet attrs) {
super(context, attrs);
init();
}
public BlurTouchImageView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
init();
}
/**
* Inits our view internal members
*/
private void init() {
mBlurScript = RenderScript.create(getContext());
mIntrinsicScript = ScriptIntrinsicBlur.create(mBlurScript, Element.U8_4(mBlurScript));
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.gimg);
mBlurredBitmap = Bitmap.createBitmap(BLUR_SIDE, BLUR_SIDE, mBitmap.getConfig());
}
@Override
public boolean onTouchEvent(final MotionEvent event) {
boolean retval = false;
mX = event.getX();
mY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
retval = true;
invalidate();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mX = -1;
mY = - 1;
retval = true;
invalidate();
break;
default:
// nothing to do here
break;
}
return retval;
}
@Override
protected void onDraw(final Canvas canvas) {
// Blur bitmap if it's touched
canvas.drawBitmap(mBitmap, 0, 0, null);
if (mX > 0 && mY > 0) {
// Yeah, it will slooow down drawing, but how else we can prepare needed part of bitmap?
final Bitmap blurSource = Bitmap.createBitmap(mBitmap, (int) mX - BLUR_SIDE / 2, (int) mY - BLUR_SIDE / 2, BLUR_SIDE, BLUR_SIDE);
final Allocation inAlloc = Allocation.createFromBitmap(mBlurScript, blurSource, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_GRAPHICS_TEXTURE);
final Allocation outAlloc = Allocation.createFromBitmap(mBlurScript, mBlurredBitmap);
mIntrinsicScript.setRadius(BLUR_RADIUS);
mIntrinsicScript.setInput(inAlloc);
mIntrinsicScript.forEach(outAlloc);
outAlloc.copyTo(mBlurredBitmap);
canvas.drawBitmap(mBlurredBitmap, (int)mX - BLUR_SIDE / 2, (int)mY - BLUR_SIDE / 2, null);
}
}
}
Result is:
Although I was afraid that creating Bitmap
in onDraw
will cause big lags, in activity with only this view blur area moves quite smoothly.
来源:https://stackoverflow.com/questions/18188079/blur-on-touch-android-application