如何借助模板的坐标裁剪图像

时间:2014-12-27 08:59:09

标签: android image bitmap crop

在我的项目中,我使用嵌套的FrameLayout。我将活动布局为:

<FrameLayout>   ---------(1)
  <SurfaceView>
     <FrameLayout> ------(2)
  </SurfaceView>
</FrameLayout>

FrameLayout(2)显示模板。该活动使用自定义相机API捕获图像。用户应该在FrameLayout(2)的模板中拟合interst的对象。在捕获图像之后,我想裁剪该图像,使得只有模板中拟合的感兴趣对象可用。原始图像被此裁剪图像覆盖。

要裁剪图片,我正在使用Bitmap.createBitmap(bitmap,int,int,int,int)。对于四个int参数,我使用getLocationInWindow(int[])getWidth()以及getHeight()。代码是:

private class SaveImageTask extends AsyncTask<byte[], Void, Void> {

     //Child frame-layout-
        final FrameLayout F1=(FrameLayout) findViewById(R.id.F1);

     //Parent frame-layout-
        final FrameLayout F=(FrameLayout) findViewById(R.id.layout);

        int a[]=new int[2];


        @Override
        protected Void doInBackground(byte[]... data) {
            FileOutputStream outStream = null;

            // Write to SD Card
            try
            {

                Bitmap bitmap;
                bitmap = BitmapFactory.decodeFile(filename_with_path);
                Bitmap newBitmap;

                if (bitmap != null) {

                 // child frame-layoout
                    F1.getLocationOnScreen(a);

                    newBitmap = Bitmap.createBitmap(bitmap,a[0], a[1],F1.getWidth(),F1.getHeight());

                    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
                    newBitmap.compress(Bitmap.CompressFormat.JPEG, 40, bytes);


                    // overwrite original image
                    FileOutputStream fo = new FileOutputStream(filename_with_path);
                    fo.write(bytes.toByteArray());
                    fo.close();

                    bitmap.recycle();
                }
                refreshGallery(outFile);
            }
            catch (Exception e) { e.printStackTrace();}

            return null;
        }
    }

但在执行此代码后,我无法获得所需的裁剪图像。裁剪后的图像不包含感兴趣的物体,而是包含原始图像的不同部分。

Bitmap.createBitmap()返回的getLocationOnScreen()和int []的int参数单位是否不同?

我们需要转换吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

好的是画布裁剪类

package com.domp.me;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;

public class TouchView extends View {

    //private final String TAG = "TESTTESTTESTESTTESTESTEST";

    private Drawable mLeftTopIcon;
    private Drawable mRightTopIcon;
    private Drawable mLeftBottomIcon;
    private Drawable mRightBottomIcon;

    private boolean mLeftTopBool = false;
    private boolean mRightTopBool = false;
    private boolean mLeftBottomBool = false;
    private boolean mRightBottomBool = false;

    // Starting positions of the bounding box

    private float mLeftTopPosX = 30;
    private float mLeftTopPosY = 120;

    private float mRightTopPosX = 150;
    private float mRightTopPosY = 120;

    private float mLeftBottomPosX = 30;
    private float mLeftBottomPosY = 200;

    private float mRightBottomPosX = 150;
    private float mRightBottomPosY = 200;
    private float mPosX;
    private float mPosY;

    private float mLastTouchX;
    private float mLastTouchY;

    private Paint topLine;
    private Paint bottomLine;
    private Paint leftLine;
    private Paint rightLine;

    private Rect buttonRec;

    private int mCenter;

    private static final int INVALID_POINTER_ID = -1;
    private int mActivePointerId = INVALID_POINTER_ID;

    // you can ignore this 
    private ScaleGestureDetector mScaleDetector;
    private float mScaleFactor = 1.f;


    public TouchView(Context context){
        super(context);
        init(context);
    }

    public TouchView(Context context, AttributeSet attrs){
        super (context,attrs);
        init(context);
    }

    public TouchView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    private void init(Context context) {

        // I need to create lines for the bouding box to connect

        topLine = new Paint();
        bottomLine = new Paint();
        leftLine = new Paint();
        rightLine = new Paint();

        setLineParameters(Color.WHITE,2);

        // Here I grab the image that will work as the corners of the bounding
        // box and set their positions.

        mLeftTopIcon = context.getResources().getDrawable(R.drawable.corners);

        mCenter = mLeftTopIcon.getMinimumHeight()/2;
        mLeftTopIcon.setBounds((int)mLeftTopPosX, (int)mLeftTopPosY,
                mLeftTopIcon.getIntrinsicWidth()+(int)mLeftTopPosX,
                mLeftTopIcon.getIntrinsicHeight()+(int)mLeftTopPosY);

        mRightTopIcon = context.getResources().getDrawable(R.drawable.corners);
        mRightTopIcon.setBounds((int)mRightTopPosX, (int)mRightTopPosY,
                mRightTopIcon.getIntrinsicWidth()+(int)mRightTopPosX,
                mRightTopIcon.getIntrinsicHeight()+(int)mRightTopPosY);

        mLeftBottomIcon = context.getResources().getDrawable(R.drawable.corners);
        mLeftBottomIcon.setBounds((int)mLeftBottomPosX, (int)mLeftBottomPosY,
                mLeftBottomIcon.getIntrinsicWidth()+(int)mLeftBottomPosX,
                mLeftBottomIcon.getIntrinsicHeight()+(int)mLeftBottomPosY);

        mRightBottomIcon = context.getResources().getDrawable(R.drawable.corners);
        mRightBottomIcon.setBounds((int)mRightBottomPosX, (int)mRightBottomPosY,
                mRightBottomIcon.getIntrinsicWidth()+(int)mRightBottomPosX,
                mRightBottomIcon.getIntrinsicHeight()+(int)mRightBottomPosY);
        // Create our ScaleGestureDetector
        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());

    }

    private void setLineParameters(int color, float width){

        topLine.setColor(color);
        topLine.setStrokeWidth(width);

        bottomLine.setColor(color);
        bottomLine.setStrokeWidth(width);

        leftLine.setColor(color);
        leftLine.setStrokeWidth(width);

        rightLine.setColor(color);
        rightLine.setStrokeWidth(width);

    }

    // Draws the bounding box on the canvas. Every time invalidate() is called
    // this onDraw method is called.
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.save();

        canvas.drawLine(mLeftTopPosX+mCenter, mLeftTopPosY+mCenter,
                mRightTopPosX+mCenter, mRightTopPosY+mCenter, topLine);
        canvas.drawLine(mLeftBottomPosX+mCenter, mLeftBottomPosY+mCenter,
                mRightBottomPosX+mCenter, mRightBottomPosY+mCenter, bottomLine);
        canvas.drawLine(mLeftTopPosX+mCenter,mLeftTopPosY+mCenter,
                mLeftBottomPosX+mCenter,mLeftBottomPosY+mCenter,leftLine);
        canvas.drawLine(mRightTopPosX+mCenter,mRightTopPosY+mCenter,
                mRightBottomPosX+mCenter,mRightBottomPosY+mCenter,rightLine);


        mLeftTopIcon.setBounds((int)mLeftTopPosX, (int)mLeftTopPosY,
                mLeftTopIcon.getIntrinsicWidth()+(int)mLeftTopPosX,
                mLeftTopIcon.getIntrinsicHeight()+(int)mLeftTopPosY);

        mRightTopIcon.setBounds((int)mRightTopPosX, (int)mRightTopPosY,
                mRightTopIcon.getIntrinsicWidth()+(int)mRightTopPosX,
                mRightTopIcon.getIntrinsicHeight()+(int)mRightTopPosY);

        mLeftBottomIcon.setBounds((int)mLeftBottomPosX, (int)mLeftBottomPosY,
                mLeftBottomIcon.getIntrinsicWidth()+(int)mLeftBottomPosX,
                mLeftBottomIcon.getIntrinsicHeight()+(int)mLeftBottomPosY);

        mRightBottomIcon.setBounds((int)mRightBottomPosX, (int)mRightBottomPosY,
                mRightBottomIcon.getIntrinsicWidth()+(int)mRightBottomPosX,
                mRightBottomIcon.getIntrinsicHeight()+(int)mRightBottomPosY);


        mLeftTopIcon.draw(canvas);
        mRightTopIcon.draw(canvas);
        mLeftBottomIcon.draw(canvas);
        mRightBottomIcon.draw(canvas);
        canvas.restore();
    }


    public boolean onTouchEvent(MotionEvent ev) {
        final int action = ev.getAction();
        boolean intercept = true;

        switch (action) {

        case MotionEvent.ACTION_DOWN: {

            final float x = ev.getX();
            final float y = ev.getY();

            // in CameraPreview we have Rect rec. This is passed here to return
            // a false when the camera button is pressed so that this view ignores
            // the touch event.
            if ((x >= buttonRec.left) && (x <=buttonRec.right) && (y>=buttonRec.top) && (y<=buttonRec.bottom)){
                intercept = false;
                break;
            }

            // is explained below, when we get to this method.
            manhattanDistance(x,y);

            // Remember where we started
            mLastTouchX = x;
            mLastTouchY = y;
            mActivePointerId = ev.getPointerId(0);
            break;
        }

        case MotionEvent.ACTION_MOVE: {

            final int pointerIndex = ev.findPointerIndex(mActivePointerId);
            final float x = ev.getX();
            final float y = ev.getY();
            //Log.i(TAG,"x: "+x);
            //Log.i(TAG,"y: "+y);

            // Only move if the ScaleGestureDetector isn't processing a gesture.
            // but we ignore here because we are not using ScaleGestureDetector.
            if (!mScaleDetector.isInProgress()) {
                final float dx = x - mLastTouchX;
                final float dy = y - mLastTouchY;

                mPosX += dx;
                mPosY += dy;

                invalidate();
            }

            // Calculate the distance moved
            final float dx = x - mLastTouchX;
            final float dy = y - mLastTouchY;


            // Move the object
            if (mPosX >= 0 && mPosX <=800){
                mPosX += dx;
            }
            if (mPosY >=0 && mPosY <= 480){
                mPosY += dy;
            }

            // while its being pressed n it does not overlap the bottom line or right line
            if (mLeftTopBool && ((y+mCenter*2) < mLeftBottomPosY) && ((x+mCenter*2) < mRightTopPosX)){
                if (dy != 0){
                    mRightTopPosY = y;
                }
                if (dx != 0){
                    mLeftBottomPosX = x;
                }
                mLeftTopPosX = x;//mPosX;
                mLeftTopPosY = y;//mPosY;
            }
            if (mRightTopBool && ((y+mCenter*2) < mRightBottomPosY) && (x > (mLeftTopPosX+mCenter*2))){
                if (dy != 0){
                    mLeftTopPosY = y;
                }
                if (dx != 0){
                    mRightBottomPosX = x;
                }
                mRightTopPosX = x;//mPosX;
                mRightTopPosY = y;//mPosY;
            }
            if (mLeftBottomBool && (y > (mLeftTopPosY+mCenter*2)) && ((x +mCenter*2) < mRightBottomPosX)){
                if (dx != 0){
                    mLeftTopPosX = x;
                }
                if (dy != 0){
                    mRightBottomPosY = y;
                }
                mLeftBottomPosX = x;
                mLeftBottomPosY = y;
            }
            if (mRightBottomBool && (y > (mLeftTopPosY+mCenter*2)) && (x > (mLeftBottomPosX+mCenter*2) )){
                if (dx != 0){
                    mRightTopPosX = x;
                }
                if (dy != 0){
                    mLeftBottomPosY = y;
                }
                mRightBottomPosX = x;
                mRightBottomPosY = y;
            }

            // Remember this touch position for the next move event
            mLastTouchX = x;
            mLastTouchY = y;

            // Invalidate to request a redraw
            invalidate();
            break;
        }
        case MotionEvent.ACTION_UP: {
            // when one of these is true, that means it can move when onDraw is called
            mLeftTopBool = false;
            mRightTopBool = false;
            mLeftBottomBool = false;
            mRightBottomBool = false;
            //mActivePointerId = INVALID_POINTER_ID;
            break;
        }

        case MotionEvent.ACTION_CANCEL: {
            mActivePointerId = INVALID_POINTER_ID;
            break;
        }

        case MotionEvent.ACTION_POINTER_UP: {
            // Extract the index of the pointer that left the touch sensor
            final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) 
            >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
            final int pointerId = ev.getPointerId(pointerIndex);
            if (pointerId == mActivePointerId) {
                // This was our active pointer going up. Choose a new
                // active pointer and adjust accordingly.
                final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                mLastTouchX = ev.getX(newPointerIndex);
                mLastTouchY = ev.getY(newPointerIndex);
                mActivePointerId = ev.getPointerId(newPointerIndex);
            }
            break;
        }
        }
        return intercept;
    }

    // Where the screen is pressed, calculate the distance closest to one of the 4 corners
    // so that it can get the pressed and moved. Only 1 at a time can be moved.
    private void manhattanDistance(float x, float y) {

        double leftTopMan = Math.sqrt(Math.pow((Math.abs((double)x-(double)mLeftTopPosX)),2)
                + Math.pow((Math.abs((double)y-(double)mLeftTopPosY)),2));

        double rightTopMan = Math.sqrt(Math.pow((Math.abs((double)x-(double)mRightTopPosX)),2)
                + Math.pow((Math.abs((double)y-(double)mRightTopPosY)),2));

        double leftBottomMan = Math.sqrt(Math.pow((Math.abs((double)x-(double)mLeftBottomPosX)),2)
                + Math.pow((Math.abs((double)y-(double)mLeftBottomPosY)),2));

        double rightBottomMan = Math.sqrt(Math.pow((Math.abs((double)x-(double)mRightBottomPosX)),2)
                + Math.pow((Math.abs((double)y-(double)mRightBottomPosY)),2));

        //Log.i(TAG,"leftTopMan: "+leftTopMan);
        //Log.i(TAG,"RightTopMan: "+rightTopMan);

        if (leftTopMan < 50){
            mLeftTopBool = true;
            mRightTopBool = false;
            mLeftBottomBool = false;
            mRightBottomBool = false;
        }
        else if (rightTopMan < 50){
            mLeftTopBool = false;
            mRightTopBool = true;
            mLeftBottomBool = false;
            mRightBottomBool = false;
        }
        else if (leftBottomMan < 50){
            mLeftTopBool = false;
            mRightTopBool = false;
            mLeftBottomBool = true;
            mRightBottomBool = false;
        }
        else if (rightBottomMan < 50){
            mLeftTopBool = false;
            mRightTopBool = false;
            mLeftBottomBool = false;
            mRightBottomBool = true;
        }

    }
    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            mScaleFactor *= detector.getScaleFactor();

            // Don't let the object get too small or too large.
            mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));

            invalidate();
            return true;
        }
    }

    public float getmLeftTopPosX(){
        return mLeftTopPosX;
    }
    public float getmLeftTopPosY(){
        return mLeftTopPosY;
    }
    public float getmRightTopPosX(){
        return mRightTopPosX;
    }
    public float getmRightTopPosY(){
        return mRightTopPosY;
    }
    public float getmLeftBottomPosX() {
        return mLeftBottomPosX;
    }
    public float getmLeftBottomPosY() {
        return mLeftBottomPosY;
    }
    public float getmRightBottomPosY() {
        return mRightBottomPosY;
    }
    public float getmRightBottomPosX() {
        return mRightBottomPosX;
    }
    public void setRec(Rect rec) {
        this.buttonRec = rec;
    }

    // calls the onDraw method, I used it in my app Translanguage OCR
    // because I have a thread that needs to invalidate, or redraw
    // you cannot call onDraw from a thread not the UI thread.
    public void setInvalidate() {
        invalidate();

    }
}

并通过此代码捕获矩形区域

package com.domp.me;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;



import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.drawable.Drawable;
import android.hardware.Camera;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.os.Environment;
import android.os.Looper;
import android.text.Layout;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import android.widget.RelativeLayout.LayoutParams;


public class CameraPreview extends Activity implements SensorEventListener {

    private Preview mPreview; 
    private ImageView mTakePicture;
    private TouchView mView;
    Display mDisplay;
    DisplayMetrics mDisplayMetrics;
 AlertDialogManager alert = new AlertDialogManager();
    private boolean mAutoFocus = true;
    ImageButton hidingcrop;
    ImageButton showgrid;
    ImageButton hidegrid;
       private Animation animShow, animHide;
    com.domp.me.GridCrop grid;
    private boolean mFlashBoolean = false;
   private RelativeLayout relative;
    private SensorManager mSensorManager;
    private Sensor mAccel;
    private boolean mInitialized = false;
    private float mLastX = 0;
    private float mLastY = 0;

    private float mLastZ = 0;
    private Rect rec = new Rect();
Camera mCamera;
    private int mScreenHeight;
    private int mScreenWidth;
    Toast t;
    private boolean mInvalidate = false;
    Animation ranim_clockwise, ranim_anticlockwise;
    private File mLocation = new File(Environment.
            getExternalStorageDirectory(),"DompitCrop.jpg");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_crop);
        t.makeText(CameraPreview.this, "When Capturing Wait 4 Seconds", Toast.LENGTH_LONG).show();
        t.makeText(CameraPreview.this, "Whe", Toast.LENGTH_SHORT).setGravity(mScreenWidth, mScreenWidth, mScreenHeight);
        if(t.makeText(CameraPreview.this, "Whe", Toast.LENGTH_LONG).getView().isShown()){
            t.makeText(CameraPreview.this, "Whe", Toast.LENGTH_LONG).cancel();
        }
        animShow = AnimationUtils.loadAnimation( this, R.anim.popup_show);
        animHide = AnimationUtils.loadAnimation( this, R.anim.wave_scale);
        relative = (RelativeLayout)findViewById(R.id.mainlayout);
        relative.startAnimation(animHide);
        mTakePicture = (ImageView) findViewById(R.id.capture);
        ranim_clockwise = AnimationUtils.loadAnimation(this,R.anim.rotate_clockwise);
        ranim_anticlockwise = AnimationUtils.loadAnimation(this,R.anim.rorate_anticlockwise);


        // the accelerometer is used for autofocus
        mSensorManager = (SensorManager) getSystemService(Context.
                SENSOR_SERVICE);
        mAccel = mSensorManager.getDefaultSensor(Sensor.
                TYPE_ACCELEROMETER);

        // get the window width and height to display buttons
        // according to device screen size
        DisplayMetrics displaymetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        mScreenHeight = displaymetrics.heightPixels;
        mScreenWidth = displaymetrics.widthPixels;
        // I need to get the dimensions of this drawable to set margins
        // for the ImageView that is used to take pictures
        Drawable mButtonDrawable = this.getResources().
        getDrawable(R.drawable.cam);



        // setting where I will draw the ImageView for taking pictures

        // rec is used for onInterceptTouchEvent. I pass this from the
        // highest to lowest layer so that when this area of the screen
        // is pressed, it ignores the TouchView events and passes it to
        // this activity so that the button can be pressed.
        rec.set((int)((double)mScreenWidth*.85),
                (int)((double)mScreenHeight*.10) ,
                (int)((double)mScreenWidth*.85)+mButtonDrawable.getMinimumWidth(), 
                (int)((double)mScreenHeight*.70)+mButtonDrawable.getMinimumHeight());
        mButtonDrawable = null;
        mTakePicture.setOnClickListener(previewListener);
        grid = (com.domp.me.GridCrop)findViewById(R.id.grid);
        Button btn = (Button)findViewById(R.id.button1);

        hidingcrop = (ImageButton) findViewById(R.id.imagecrope);
        hidingcrop.setOnClickListener(mylistener);
        btn.setOnClickListener(flashListener);
        // get our Views from the XML layout
        mPreview = (Preview) findViewById(R.id.preview);
        mView = (TouchView) findViewById(R.id.left_top_view);
        mView.setRec(rec);

    }

    // this is the autofocus call back
    private AutoFocusCallback myAutoFocusCallback = new AutoFocusCallback(){

        public void onAutoFocus(boolean autoFocusSuccess, Camera arg1) {
            //Wait.oneSec();
            mAutoFocus = true;
        }};

        // with this I get the ratio between screen size and pixels
        // of the image so I can capture only the rectangular area of the
        // image and save it.
        public Double[] getRatio(){
            Size s = mPreview.getCameraParameters().getPreviewSize();
            double heightRatio = (double)s.height/(double)mScreenHeight;
            double widthRatio = (double)s.width/(double)mScreenWidth;
            Double[] ratio = {heightRatio,widthRatio};
            return ratio;
        }
        public void release(){
            mCamera.release();
            }
            private OnClickListener mylistener = new OnClickListener(){

                @Override
                public void onClick(View arg0) {

                        Camera camera = null;
                        try {
                            camera = Camera.open();
                        } catch (RuntimeException e) {

                        } finally {
                            if (camera != null) camera.release();
                            Intent i = new Intent(CameraPreview.this, BackScreenTry.class);
                            startActivity(i);
                            finish();
                        }


                }

                }

            ;
        // I am not using this in this example, but its there if you want
        // to turn on and off the flash.

        private OnClickListener flashListener = new OnClickListener(){

            @Override
            public void onClick(View v) {

                    mPreview.setFlash(true);

                mFlashBoolean = !mFlashBoolean;
            }

        };


        // This method takes the preview image, grabs the rectangular
        // part of the image selected by the bounding box and saves it.
        // A thread is needed to save the picture so not to hold the UI thread.
        private OnClickListener previewListener = new OnClickListener() {

            @Override
            public void onClick(View v) {
                    mPreview.setCameraFocus(myAutoFocusCallback);

                    Thread tGetPic = new Thread( new Runnable() {

                        public void run() {
                            Double[] ratio = getRatio();
                            int left = (int) (ratio[1]*(double)mView.getmLeftTopPosX());
                            // 0 is height
                            int top = (int) (ratio[0]*(double)mView.getmLeftTopPosY());

                            int right = (int)(ratio[1]*(double)mView.getmRightBottomPosX());

                            int bottom = (int)(ratio[0]*(double)mView.getmRightBottomPosY());

                            savePhoto(mPreview.getPic(left,top,right,bottom));
                            mAutoFocus = true;




                        } 
                    });
                    tGetPic.start();
                    Wait.oneSec();
                    Intent i = new Intent(CameraPreview.this, AnimationScreenForCrop.class);
                    startActivity(i);
                    finish();
                    }

                }

        ;



        public boolean savePhoto(Bitmap bm) {
            System.gc();
            FileOutputStream image = null;
            try {
                image = new FileOutputStream(mLocation);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            bm.compress(CompressFormat.JPEG, 100, image);

            int h = bm.getHeight();
            int w = bm.getWidth();


            return false;

        }

        public boolean onInterceptTouchEvent(MotionEvent ev) {
            final int action = ev.getAction();
            boolean intercept = false;
            switch (action) {
            case MotionEvent.ACTION_UP:
                break;
            case MotionEvent.ACTION_DOWN:
                float x = ev.getX();
                float y = ev.getY();
                // here we intercept the button press and give it to this 
                // activity so the button press can happen and we can take 
                // a picture.
                if ((x >= rec.left) && (x <= rec.right) && (y>=rec.top) && (y<=rec.bottom)){
                    intercept = true;
                }
                break;
            }
            return intercept;
        }

        // mainly used for autofocus to happen when the user takes a picture
        // I also use it to redraw the canvas using the invalidate() method
        // when I need to redraw things.
        public void onSensorChanged(SensorEvent event) {



            if (mInvalidate == true){
                mView.invalidate();
                mInvalidate = false;
            }
            float x = event.values[0];
            float y = event.values[1];
            float z = event.values[2];
            if (!mInitialized){
                mLastX = x;
                mLastY = y;
                mLastZ = z;
                mInitialized = true;
            }
            float deltaX  = Math.abs(mLastX - x);
            float deltaY = Math.abs(mLastY - y);
            float deltaZ = Math.abs(mLastZ - z);

            if (deltaX > .5 && mAutoFocus){ //AUTOFOCUS (while it is not autofocusing)
                mAutoFocus = false;
                mPreview.setCameraFocus(myAutoFocusCallback);
            }
            if (deltaY > .5 && mAutoFocus){ //AUTOFOCUS (while it is not autofocusing)
                mAutoFocus = false;
                mPreview.setCameraFocus(myAutoFocusCallback);
            }

            if (deltaZ > .5 && mAutoFocus){ //AUTOFOCUS (while it is not autofocusing) */
                mAutoFocus = false;
                mPreview.setCameraFocus(myAutoFocusCallback);
            }

            mLastX = x;
            mLastY = y;
            mLastZ = z;

        }


        // extra overrides to better understand app lifecycle and assist debugging
        @Override
        protected void onDestroy() {
            super.onDestroy();
            //Log.i(TAG, "onDestroy()");
        }

        @Override
        protected void onPause() {
            super.onPause();
            //Log.i(TAG, "onPause()");
            mSensorManager.unregisterListener(this);
        }

        @Override
        protected void onResume() {
            super.onResume();
            mSensorManager.registerListener(this, mAccel, SensorManager.SENSOR_DELAY_UI);
            //Log.i(TAG, "onResume()");
        }

        @Override
        protected void onRestart() {
            super.onRestart();
            //Log.i(TAG, "onRestart()");
        }

        @Override
        protected void onStop() {
            super.onStop();
            //Log.i(TAG, "onStop()");
        }

        @Override
        protected void onStart() {
            super.onStart();
            //Log.i(TAG, "onStart()");
        }
        @Override
        public void onAccuracyChanged(Sensor arg0, int arg1) {

}
}

享受:)