title: move,scale and crop the image in android like facebook profile picture
body: <p>I want crop an image in my application.I tried a lot but not succeed.<strong><em>Its challenge to android developer.</em></strong>
  Is there any idea or reference to implement the features move,scale and crop the image in android like facebook upload profile pic.
  Now i am able to move, scale and crop and the image.But not consistant like facebook.I want to set fix image scale based on orientation.I attached the screen shot-3.</p>
  
  <p>My code as below:-</p>
  
  <p>crop_image.xml</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:gravity="center"
      android:orientation="vertical" &gt;
  
      &lt;FrameLayout
          android:id="@+id/flCrop"
          android:layout_width="fill_parent"
          android:layout_height="0dp"
          android:layout_weight="1" &gt;
  
          &lt;ImageView
              android:id="@+id/img"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:scaleType="matrix"
              android:src="@drawable/nature" /&gt;
  
          &lt;ImageView
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:layout_gravity="center"
              android:scaleType="fitXY"
              android:src="@drawable/blur_with_frame"
              android:visibility="visible" /&gt;
  
          &lt;ImageView
              android:id="@+id/troll_face"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_marginBottom="5dp"
              android:layout_marginLeft="10dp"
              android:layout_gravity="bottom" /&gt;
      &lt;/FrameLayout&gt;
  
      &lt;LinearLayout
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:gravity="center"
          android:orientation="horizontal" &gt;
  
          &lt;Button
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:onClick="btnSelectPic"
              android:layout_marginRight="10dp"
              android:text="select Pic" /&gt;
  
          &lt;Button
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_marginLeft="10dp"
              android:onClick="btnCrop"
              android:text="Crop" /&gt;
      &lt;/LinearLayout&gt;
  
  &lt;/LinearLayout&gt;
  </code></pre>
  
  <p>MainActivity.java</p>
  
  <pre><code>package com.hotveryspicy.maskimage;
  
  import android.app.Activity;
  import android.content.Intent;
  import android.graphics.Bitmap;
  import android.graphics.BitmapFactory;
  import android.graphics.Matrix;
  import android.graphics.PointF;
  import android.net.Uri;
  import android.os.Bundle;
  import android.util.FloatMath;
  import android.util.Log;
  import android.view.MotionEvent;
  import android.view.View;
  import android.view.View.OnTouchListener;
  import android.view.ViewTreeObserver.OnGlobalLayoutListener;
  import android.widget.FrameLayout;
  import android.widget.ImageView;
  import android.widget.ImageView.ScaleType;
  
  import com.ipaulpro.afilechooser.utils.FileUtils;
  
  public class MainActivity extends Activity implements OnTouchListener{
      ImageView img;
      FrameLayout flCrop;
  
      int framWidth = 0;
      int framHeight = 0;
  
      int imageHeight ;
      int imageWidth ;
  
      int cropImageWidth = 320;
      int cropImageHeight = 263;
  
      public static int SELECT_PHOTO =0;
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.crop_image);
          img = (ImageView) findViewById(R.id.img);
          flCrop = (FrameLayout) findViewById(R.id.flCrop);
          img.setOnTouchListener(this);
  
  
      }
  
      public void btnCrop(View v) {
          ImageView troll_face = (ImageView) findViewById(R.id.troll_face);
          makeMaskImage(troll_face, R.drawable.nature);
      }
  
      public void btnSelectPic(View v){
          Intent intent = new Intent(Intent.ACTION_PICK,
                  android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
          startActivityForResult(intent, 0);
      }
  
      @Override
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
          super.onActivityResult(requestCode, resultCode, data);
  
          switch (resultCode) {
          case RESULT_OK:
              Uri targetUri = data.getData();
  
              final String path = FileUtils.getPath(this, targetUri);
  
              BitmapFactory.Options options = new BitmapFactory.Options();
              options.inJustDecodeBounds = true;
  
              Bitmap bitmap = null;
              try {
  
                  bitmap = BitmapFactory
                          .decodeFile(path);
              } catch (Exception e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              }
              imageHeight = options.outHeight;
              imageWidth = options.outWidth;
  
              img.setOnTouchListener(MainActivity.this);
  
              img.setImageBitmap(bitmap);
  
              break;
          }
      }
  
      // Method of creating mask runtime
      public void makeMaskImage(ImageView mImageView, int mContent) {
  
          flCrop.setDrawingCacheEnabled(true);
          Bitmap bitmap = Bitmap.createBitmap(flCrop.getDrawingCache());
          flCrop.setDrawingCacheEnabled(false);
  
          Log.e("TEST", "Frame W : " + framWidth + " H : " + framHeight);
          Log.e("TEST",
                  "Bitmap W : " + bitmap.getWidth() + " H : "
                          + bitmap.getHeight());
  
          Bitmap result = Bitmap.createBitmap(bitmap, (framWidth / 2)
                  - (cropImageWidth / 2) +1, (framHeight / 2)
                  - (cropImageHeight / 2), cropImageWidth -2, cropImageHeight);
          mImageView.setImageBitmap(result);
          mImageView.setScaleType(ScaleType.CENTER);
          // mImageView.setBackgroundResource(R.drawable.frame);
      }
  
  
  
  
  
      @Override
        public boolean onTouch(View v, MotionEvent event) {
              // handle touch events here
              ImageView view = (ImageView) v;
              switch (event.getAction() &amp; MotionEvent.ACTION_MASK) {
                  case MotionEvent.ACTION_DOWN:
                      savedMatrix.set(matrix);
                      start.set(event.getX(), event.getY());
                      mode = DRAG;
                      lastEvent = null;
                      break;
                  case MotionEvent.ACTION_POINTER_DOWN:
                      oldDist = spacing(event);
                      if (oldDist &gt; 10f) {
                          savedMatrix.set(matrix);
                          midPoint(mid, event);
                          mode = ZOOM;
                      }
                      lastEvent = new float[4];
                      lastEvent[0] = event.getX(0);
                      lastEvent[1] = event.getX(1);
                      lastEvent[2] = event.getY(0);
                      lastEvent[3] = event.getY(1);
                      d = rotation(event);
                      Log.e("MainActivity","MainActivity down d = "+d);
                      break;
                  case MotionEvent.ACTION_UP:
                  case MotionEvent.ACTION_POINTER_UP:
                      mode = NONE;
                      lastEvent = null;
                      break;
                  case MotionEvent.ACTION_MOVE:
                      if (mode == DRAG) {
                          matrix.set(savedMatrix);
                          float dx = event.getX() - start.x;
                          float dy = event.getY() - start.y;
                          Log.e("TEST","Dx : "+ dx+" Dy : "+ dy);
                          matrix.postTranslate(dx, dy);
                      } else if (mode == ZOOM) {
                          float newDist = spacing(event);
                          if (newDist &gt; 10f) {
                              matrix.set(savedMatrix);
                              float scale = (newDist / oldDist);
                              matrix.postScale(scale, scale, mid.x, mid.y);
                          }
                          if (lastEvent != null &amp;&amp; event.getPointerCount() == 3) {
                              newRot = rotation(event);
                              Log.e("MainActivity","MainActivity move d= "+d);
                              float r = newRot - d;
                              float[] values = new float[9];
                              matrix.getValues(values);
                              float tx = values[2];
                              float ty = values[5];
                              float sx = values[0];
                              float xc = (view.getWidth() / 2) * sx;
                              float yc = (view.getHeight() / 2) * sx;
                              matrix.postRotate(r, tx + xc, ty + yc);
                          }
                      }
                      break;
                   default:
                       view.setImageMatrix(matrix);
                       return true;
              }
              view.setImageMatrix(matrix);
              return true;
          }
  
          /**
           * Determine the space between the first two fingers
           */
          private float spacing(MotionEvent event) {
              float x = event.getX(0) - event.getX(1);
              float y = event.getY(0) - event.getY(1);
              return FloatMath.sqrt(x * x + y * y);
          }
  
          /**
           * Calculate the mid point of the first two fingers
           */
          private void midPoint(PointF point, MotionEvent event) {
              float x = event.getX(0) + event.getX(1);
              float y = event.getY(0) + event.getY(1);
              point.set(x / 2, y / 2);
          }
  
          /**
           * Calculate the degree to be rotated by.
           *
           * @param event
           * @return Degrees
           */
          private float rotation(MotionEvent event) {
              double delta_x = (event.getX(0) - event.getX(1));
              double delta_y = (event.getY(0) - event.getY(1));
              double radians = Math.atan2(delta_y, delta_x);
              return (float) Math.toDegrees(radians);
          }
          // these matrices will be used to move and zoom image
          private static Matrix matrix = new Matrix();
          private static Matrix savedMatrix = new Matrix();
          // we can be in one of these 3 states
          private static final int NONE = 0;
          private static final int DRAG = 1;
          private static final int ZOOM = 2;
          private int mode = NONE;
          // remember some things for zooming
          private PointF start = new PointF();
          private PointF mid = new PointF();
          private float oldDist = 1f;
          private float d = 0f;
          private float newRot = 0f;
          private float[] lastEvent = null;
  
          boolean flag ;
  }
  </code></pre>
  
  <p>Looking my demo like:-</p>
  
  <p>Screenshot-1
  <img src="https://i.stack.imgur.com/Ao3Di.png" alt="Screenshot-1"></p>
  
  <p>When zoom-out its looking as below image:-
  Screenshot-2
  <img src="https://i.stack.imgur.com/KTrQ1.png" alt="Screenshot-2"></p>
  
  <p>What exactly i am looking the solution :- 
  Screenshot-3</p>
  
  <p><img src="https://i.stack.imgur.com/WXZfi.png" alt="Screenshot-3"></p>
  
  <p>If anyone have idea.Please help me.Thanks in advance...</p>