手指触摸的Android模糊效果
问题描述:
大家好我是Android的新手我正在开发一个应用程序,其中我想添加从照片库中选择或从相机捕获的照片模糊效果。在我的要求中,我必须在用户触摸的那部分照片上显示模糊效果。我搜索并阅读教程和博客,也使用github存储库,但未能找到一些有用的信息。给我一些有用的教程或方法。我会非常感激。手指触摸的Android模糊效果
答
这是我用来模糊手指移动图像的工作代码。无论你将手指移动哪个部分都会模糊。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Calendar;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Toast;
public class MainActivity extends Activity {
public static Paint mPaint;
public static Path mPath;
protected Bitmap backgroundImage;
protected static Canvas myCanvas = null;
int dispHeight;
int dispWidth;
boolean flagProgress = false;
int blurSize = 4;
String picturePath = "";
float Orientation;
int MaxResolution, maxHeightResolution;
boolean blurBoolean = false;
private Drawable bluredImageBackground = null;
private Button blurr;
protected static Bitmap overlay = null;
protected static Bitmap topBitmap = null, bottomBitmap = null;
boolean booleanBlur = false;
boolean booleanUndo = false;
Button brushSizeButton;
int buildVersion;
int count = 0;
boolean edited = false;
public static Bitmap foregroundbitmap;
int height;
int imageheight;
int imagwidth;
File isfile;
public static MyFingerTap myInvalidate;
int pos;
RelativeLayout relativeLayout;
Bitmap resisedbitmap;
SeekBar seekBar;
Button shareButton;
Bitmap bitmapImage;
String shareImageFileName;
int size = 30;
RelativeLayout subrelativeLayout;
View viewHorizontalRect;
Button undoButton;
int width;
private SeekBar seek_bar;
float mX, mY;
private RelativeLayout super_layout;
public static Bitmap bitmap;
private ImageView mirro_image;
// /////////////////////////////////////////
private ImageView image_blur, image_save, image_undo, image_effect,
image_share;
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
seek_bar = (SeekBar) findViewById(R.id.seek_bar);
Display localDisplay = getWindowManager().getDefaultDisplay();
localDisplay.getHeight();
int i = localDisplay.getWidth();
int j = localDisplay.getHeight();
MaxResolution = i;
imagwidth = 100;
imageheight = 100;
maxHeightResolution = j;
super_layout = (RelativeLayout) findViewById(R.id.super_layout);
// this.picturePath = getIntent().getStringExtra("path");
// this.Orientation = getCameraPhotoOrientation(this.picturePath);
// getAspectRatio(this.picturePath);
// foregroundbitmap = getResizedOriginalBitmap(this.imagwidth,
// this.imageheight);
foregroundbitmap = Bitmap.createScaledBitmap(SplashActivity.passBitmap,
i, 550, true);
if (foregroundbitmap == null) {
Toast.makeText(getApplicationContext(), "Image not Suuported", 0)
.show();
finish();
}
// /////////////////////////////
topBitmap = foregroundbitmap;
bottomBitmap = foregroundbitmap;
overlay = Bitmap.createBitmap(foregroundbitmap.getWidth(),
foregroundbitmap.getHeight(), Bitmap.Config.ARGB_8888);
// ///////////////////////////////////////////////
if (foregroundbitmap == null || overlay == null) {
Toast.makeText(MainActivity.this, "bitmap is null",
Toast.LENGTH_LONG).show();
}
initializePaint(20);
seek_bar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar arg0) {
}
@Override
public void onStartTrackingTouch(SeekBar arg0) {
}
@Override
public void onProgressChanged(SeekBar arg0, int value, boolean arg2) {
setpaintSize(value);
}
});
callAsynk();
super_layout.addView(new MyFingerTap(MainActivity.this));
}
private void init() {
mirro_image = (ImageView) findViewById(R.id.mirro_image);
image_blur = (ImageView) findViewById(R.id.image_blur);
image_save = (ImageView) findViewById(R.id.image_save);
image_undo = (ImageView) findViewById(R.id.image_undo);
image_effect = (ImageView) findViewById(R.id.image_effect);
image_share = (ImageView) findViewById(R.id.image_share);
image_blur.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
if (super_layout.getVisibility() == View.GONE) {
super_layout.setVisibility(View.VISIBLE);
mirro_image.setVisibility(View.GONE);
}
}
});
image_save.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (super_layout.getVisibility() == View.VISIBLE) {
super_layout.setDrawingCacheEnabled(true);
super_layout.buildDrawingCache();
Bitmap bitmap = super_layout.getDrawingCache();
saveBitmap(bitmap);
} else {
if (passBitmap != null)
saveBitmap(passBitmap);
}
}
});
image_undo.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
callAsynk();
}
});
image_effect.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
applyEffect();
}
});
image_share.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
shareBitmap();
}
});
}
public Bitmap passBitmap;
protected void applyEffect() {
super_layout.setDrawingCacheEnabled(true);
super_layout.buildDrawingCache();
Bitmap bitmap = super_layout.getDrawingCache();
passBitmap = BitmapProcesser.Mode_1_A(Bitmap.createBitmap(bitmap));
super_layout.setVisibility(View.GONE);
mirro_image.setVisibility(View.VISIBLE);
mirro_image.setImageBitmap(passBitmap);
}
public void saveBitmap(Bitmap bmp) {
String _time = "";
Calendar cal = Calendar.getInstance();
int millisecond = cal.get(Calendar.MILLISECOND);
int second = cal.get(Calendar.SECOND);
int minute = cal.get(Calendar.MINUTE);
int hourofday = cal.get(Calendar.HOUR_OF_DAY);
_time = "image_" + hourofday + "" + minute + "" + second + ""
+ millisecond + ".png";
String file_path = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/BlurBackgroundImage";
try {
File dir = new File(file_path);
if (!dir.exists())
dir.mkdirs();
File file = new File(dir, _time);
FileOutputStream fOut = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 90, fOut);
fOut.flush();
fOut.close();
Toast.makeText(getApplicationContext(),
"Image has been saved in BlurBackgroundImage folder",
Toast.LENGTH_LONG).show();
} catch (Exception e) {
Log.e("error in saving image", e.getMessage());
}
}
protected void shareBitmap() {
Bitmap bitmap = null;
if (super_layout.getVisibility() == View.VISIBLE) {
super_layout.invalidate();
super_layout.setDrawingCacheEnabled(true);
super_layout.buildDrawingCache();
bitmap = super_layout.getDrawingCache();
} else {
super_layout.invalidate();
bitmap = passBitmap;
}
File root = Environment.getExternalStorageDirectory();
final File cachePath = new File(root.getAbsolutePath()
+ "/DCIM/Camera/image.jpg");
try {
cachePath.createNewFile();
FileOutputStream ostream = new FileOutputStream(cachePath);
bitmap.compress(CompressFormat.JPEG, 100, ostream);
ostream.flush();
ostream.close();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_STREAM,
Uri.fromFile(new File(cachePath.getAbsolutePath())));
startActivity(intent);
}
}, 1000);
} catch (Exception e) {
}
}
public void callAsynk() {
new BackgroundRunner().execute("");
}
public class BackgroundRunner extends AsyncTask<String, Void, String> {
protected void onPostExecute(String paramString) {
MainActivity.bottomBitmap = MainActivity.foregroundbitmap;
MainActivity.topBitmap = MainActivity.this.backgroundImage;
MainActivity.myCanvas.drawBitmap(MainActivity.bottomBitmap, 0.0F,
0.0F, null);
MainActivity.myInvalidate.invalidate();
}
@Override
protected String doInBackground(String... arg0) {
MainActivity.this.backgroundImage = MainActivity.this.fastblur(
MainActivity.foregroundbitmap, 10);
return null;
}
}
public void initializePaint(int paramInt) {
mPath = new Path();
myCanvas = new Canvas();
myCanvas.setBitmap(overlay);
mPaint = new Paint();
myCanvas.drawBitmap(MainActivity.foregroundbitmap, 0.0F, 0.0F, null);
myCanvas.drawBitmap(MainActivity.foregroundbitmap, 0.0F, 0.0F, mPaint);
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(paramInt);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
mPaint.setAntiAlias(true);
mPaint.setFilterBitmap(false);
}
private void setpaintSize(int size) {
mPaint.setStrokeWidth(size);
}
private void getAspectRatio(String paramString) {
BitmapFactory.Options localOptions = new BitmapFactory.Options();
localOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(paramString, localOptions);
float f1 = localOptions.outWidth/localOptions.outHeight;
float f3 = 0;
float f2 = 0;
if (f1 > 1.0F) {
f3 = this.MaxResolution;
f2 = f3/f1;
}
while (true) {
this.imagwidth = (int) f3;
this.imageheight = (int) f2;
f2 = this.MaxResolution;
f3 = f2 * f1;
break;
}
}
public static int getCameraPhotoOrientation(String paramString) {
try {
int i = new ExifInterface(new File(paramString).getPath())
.getAttributeInt("Orientation", 1);
switch (i) {
case 4:
case 5:
case 7:
default:
return 0;
case 8:
return 270;
case 3:
return 180;
case 6:
}
return 90;
} catch (Exception localException) {
localException.printStackTrace();
}
return 0;
}
private Bitmap getResizedOriginalBitmap(int paramInt1, int paramInt2) {
try {
BitmapFactory.Options localOptions = new BitmapFactory.Options();
localOptions.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(this.picturePath),
null, localOptions);
int i = localOptions.outWidth;
int j = localOptions.outHeight;
int k = 1;
while (true) {
if (i/2 <= paramInt1) {
float f1 = paramInt1/i;
float f2 = paramInt2/j;
localOptions.inJustDecodeBounds = false;
localOptions.inDither = false;
localOptions.inSampleSize = k;
localOptions.inScaled = false;
localOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap localBitmap = BitmapFactory.decodeStream(
new FileInputStream(this.picturePath), null,
localOptions);
Matrix localMatrix = new Matrix();
localMatrix.postRotate(this.Orientation);
return Bitmap.createBitmap(localBitmap, 0, 0,
localBitmap.getWidth(), localBitmap.getHeight(),
localMatrix, true);
}
i /= 2;
j /= 2;
k *= 2;
}
} catch (Exception e) {
Log.e("this is exception", "" + e.getMessage());
}
return null;
}
public Bitmap fastblur(Bitmap sentBitmap, int radius) {
Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
if (radius < 1) {
return (null);
}
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int[] pix = new int[w * h];
bitmap.getPixels(pix, 0, w, 0, 0, w, h);
int wm = w - 1;
int hm = h - 1;
int wh = w * h;
int div = radius + radius + 1;
int r[] = new int[wh];
int g[] = new int[wh];
int b[] = new int[wh];
int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
int vmin[] = new int[Math.max(w, h)];
int divsum = (div + 1) >> 1;
divsum *= divsum;
int dv[] = new int[256 * divsum];
for (i = 0; i < 256 * divsum; i++) {
dv[i] = (i/divsum);
}
yw = yi = 0;
int[][] stack = new int[div][3];
int stackpointer;
int stackstart;
int[] sir;
int rbs;
int r1 = radius + 1;
int routsum, goutsum, boutsum;
int rinsum, ginsum, binsum;
for (y = 0; y < h; y++) {
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
for (i = -radius; i <= radius; i++) {
p = pix[yi + Math.min(wm, Math.max(i, 0))];
sir = stack[i + radius];
sir[0] = (p & 0xff0000) >> 16;
sir[1] = (p & 0x00ff00) >> 8;
sir[2] = (p & 0x0000ff);
rbs = r1 - Math.abs(i);
rsum += sir[0] * rbs;
gsum += sir[1] * rbs;
bsum += sir[2] * rbs;
if (i > 0) {
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
} else {
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
}
}
stackpointer = radius;
for (x = 0; x < w; x++) {
r[yi] = dv[rsum];
g[yi] = dv[gsum];
b[yi] = dv[bsum];
rsum -= routsum;
gsum -= goutsum;
bsum -= boutsum;
stackstart = stackpointer - radius + div;
sir = stack[stackstart % div];
routsum -= sir[0];
goutsum -= sir[1];
boutsum -= sir[2];
if (y == 0) {
vmin[x] = Math.min(x + radius + 1, wm);
}
p = pix[yw + vmin[x]];
sir[0] = (p & 0xff0000) >> 16;
sir[1] = (p & 0x00ff00) >> 8;
sir[2] = (p & 0x0000ff);
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
rsum += rinsum;
gsum += ginsum;
bsum += binsum;
stackpointer = (stackpointer + 1) % div;
sir = stack[(stackpointer) % div];
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
rinsum -= sir[0];
ginsum -= sir[1];
binsum -= sir[2];
yi++;
}
yw += w;
}
for (x = 0; x < w; x++) {
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
yp = -radius * w;
for (i = -radius; i <= radius; i++) {
yi = Math.max(0, yp) + x;
sir = stack[i + radius];
sir[0] = r[yi];
sir[1] = g[yi];
sir[2] = b[yi];
rbs = r1 - Math.abs(i);
rsum += r[yi] * rbs;
gsum += g[yi] * rbs;
bsum += b[yi] * rbs;
if (i > 0) {
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
} else {
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
}
if (i < hm) {
yp += w;
}
}
yi = x;
stackpointer = radius;
for (y = 0; y < h; y++) {
pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16)
| (dv[gsum] << 8) | dv[bsum];
rsum -= routsum;
gsum -= goutsum;
bsum -= boutsum;
stackstart = stackpointer - radius + div;
sir = stack[stackstart % div];
routsum -= sir[0];
goutsum -= sir[1];
boutsum -= sir[2];
if (x == 0) {
vmin[y] = Math.min(y + r1, hm) * w;
}
p = x + vmin[y];
sir[0] = r[p];
sir[1] = g[p];
sir[2] = b[p];
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
rsum += rinsum;
gsum += ginsum;
bsum += binsum;
stackpointer = (stackpointer + 1) % div;
sir = stack[stackpointer];
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
rinsum -= sir[0];
ginsum -= sir[1];
binsum -= sir[2];
yi += w;
}
}
bitmap.setPixels(pix, 0, w, 0, 0, w, h);
return (bitmap);
}
@SuppressLint({ "NewApi" })
Bitmap BlurImage(Bitmap paramBitmap) {
try {
RenderScript localRenderScript = RenderScript
.create(getApplicationContext());
Allocation localAllocation1 = Allocation.createFromBitmap(
localRenderScript, paramBitmap);
ScriptIntrinsicBlur localScriptIntrinsicBlur = ScriptIntrinsicBlur
.create(localRenderScript, Element.U8_4(localRenderScript));
localScriptIntrinsicBlur.setRadius(4.0F);
localScriptIntrinsicBlur.setInput(localAllocation1);
Bitmap localBitmap = Bitmap.createBitmap(paramBitmap.getWidth(),
paramBitmap.getHeight(), Bitmap.Config.ARGB_8888);
Allocation localAllocation2 = Allocation.createFromBitmap(
localRenderScript, localBitmap);
localScriptIntrinsicBlur.forEach(localAllocation2);
localAllocation2.copyTo(localBitmap);
localRenderScript.destroy();
return localBitmap;
} catch (Exception localException) {
}
return paramBitmap;
}
public Bitmap getResizedBitmap(Bitmap paramBitmap, int paramInt1,
int paramInt2) {
int i = paramBitmap.getWidth();
int j = paramBitmap.getHeight();
float f1 = paramInt2/i;
float f2 = paramInt1/j;
Matrix localMatrix = new Matrix();
localMatrix.postScale(10, 10);
return Bitmap.createBitmap(paramBitmap, 0, 0, i, j, localMatrix, false);
}
@SuppressLint({ "ClickableViewAccessibility" })
public static class MyFingerTap extends View {
private static final float MAX_VAL = 4.0F;
private Path mPath;
private float mX;
private float mY;
public MyFingerTap(Context paramContext) {
super(paramContext);
this.mPath = new Path();
MainActivity.myInvalidate = this;
}
public MyFingerTap(Context paramContext, AttributeSet paramAttributeSet) {
super(paramContext);
MainActivity.myInvalidate = this;
}
private void touchMove(float paramFloat1, float paramFloat2) {
float f1 = Math.abs(paramFloat1 - this.mX);
float f2 = Math.abs(paramFloat2 - this.mY);
if ((f1 >= 4.0F) || (f2 >= 4.0F)) {
this.mPath.quadTo(this.mX, this.mY,
(paramFloat1 + this.mX)/2.0F,
(paramFloat2 + this.mY)/2.0F);
this.mX = paramFloat1;
this.mY = paramFloat2;
}
}
private void touchStart(float paramFloat1, float paramFloat2) {
this.mPath.reset();
this.mPath.moveTo(paramFloat1, paramFloat2);
MainActivity.myCanvas.drawPoint(paramFloat1, paramFloat2,
MainActivity.mPaint);
this.mX = paramFloat1;
this.mY = paramFloat2;
}
private void touchUp() {
this.mPath.lineTo(this.mX, this.mY);
MainActivity.myCanvas.drawPath(this.mPath, MainActivity.mPaint);
this.mPath.reset();
}
protected void onDraw(Canvas paramCanvas) {
paramCanvas.drawBitmap(MainActivity.topBitmap, 0.0F, 0.0F, null);
MainActivity.myCanvas.drawPath(this.mPath, MainActivity.mPaint);
paramCanvas.drawBitmap(MainActivity.overlay, 0.0F, 0.0F, null);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchStart(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touchMove(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touchUp();
invalidate();
break;
}
return true;
}
}
}
下面是XML文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg2" >
<RelativeLayout
android:id="@+id/super_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/seek_bar"
android:layout_centerInParent="true"
android:layout_marginBottom="15dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="10dp"
android:visibility="visible" />
<ImageView
android:id="@+id/mirro_image"
android:layout_width="fill_parent"
android:layout_height="400dp"
android:layout_above="@+id/seek_bar"
android:layout_centerInParent="true"
android:layout_marginBottom="15dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="10dp"
android:contentDescription="@null"
android:visibility="gone" />
<SeekBar
android:id="@+id/seek_bar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="70dp"
android:indeterminate="false"
android:max="100"
android:progress="20"
android:progressDrawable="@drawable/seek_bar_process"
android:thumb="@drawable/scroll_bar2" />
<LinearLayout
android:id="@+id/footer"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
android:background="@drawable/secondstrip"
android:gravity="center_vertical"
android:orientation="horizontal"
android:weightSum="5" >
<ImageView
android:id="@+id/image_blur"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:contentDescription="@null"
android:padding="3dp"
android:src="@drawable/blur_icon" />
<ImageView
android:id="@+id/image_undo"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:contentDescription="@null"
android:padding="3dp"
android:src="@drawable/undo_icon" />
<ImageView
android:id="@+id/image_effect"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:contentDescription="@null"
android:padding="3dp"
android:src="@drawable/effect_icon" />
<ImageView
android:id="@+id/image_save"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:contentDescription="@null"
android:padding="3dp"
android:src="@drawable/save" />
<ImageView
android:id="@+id/image_share"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:contentDescription="@null"
android:padding="3dp"
android:src="@drawable/share_icon" />
</LinearLayout>
</RelativeLayout>