title: Crop bitmap with Path object
body: <p>In my app I try to crop bitmap from selected user shape.
  I have read a lot about this issue and still I cant find any solution.
  The image I get after the cropping is not the image that I have marked.</p>
  
  <p>Here is my code:</p>
  
  <pre><code>public class TestView extends ImageView implements OnTouchListener {
      private Paint paint;
      public static List&lt;Point&gt; points;
  
      Bitmap bitmapMain;
  
      Context mContext;
  
      private int leftX = 0;
      private int rightX = 0;
      private int upY = 0;
      private int downY = 0;
  
      public TestView(Context c) {
          super(c);
  
          mContext = c;
          setFocusable(true);
          setFocusableInTouchMode(true);
  
          paint = new Paint(Paint.ANTI_ALIAS_FLAG);
          paint.setStyle(Paint.Style.STROKE);
          paint.setPathEffect(new DashPathEffect(new float[] { 10, 20 }, 0));
          paint.setStrokeWidth(5);
          paint.setColor(Color.WHITE);
  
          this.setOnTouchListener(this);
          points = new ArrayList&lt;Point&gt;();
  
  
      }
  
      public TestView(Context context, AttributeSet attrs) {
          super(context, attrs);
          mContext = context;
          setFocusable(true);
          setFocusableInTouchMode(true);
  
          paint = new Paint(Paint.ANTI_ALIAS_FLAG);
          paint.setStyle(Paint.Style.STROKE);
          paint.setStrokeWidth(2);
          paint.setColor(Color.WHITE);
  
          this.setOnTouchListener(this);
          points = new ArrayList&lt;Point&gt;();
  
      }
  
      public void setBitmap(Bitmap bit)
      {
          bitmapMain = bit;
      }
  
      public void onDraw(Canvas canvas) {
          super.onDraw(canvas);
  
         // canvas.drawBitmap(bitmap, 0, 0, null);
  
          Path path = new Path();
          boolean first = true;
  
          for (int i = 0; i &lt; points.size(); i += 2) {
              Point point = points.get(i);
              if (first) {
                  first = false;
                  path.moveTo(point.x, point.y);
              } else if (i &lt; points.size() - 1) {
                  Point next = points.get(i + 1);
                  path.quadTo(point.x, point.y, next.x, next.y);
              } else {
                  path.lineTo(point.x, point.y);
              }
          }
          canvas.drawPath(path, paint);
      }
  
      public boolean onTouch(View view, MotionEvent event) {
  
  
          if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_OUTSIDE || event.getAction() == MotionEvent.ACTION_CANCEL) 
          {
               return true;
          }
  
          int intX = (int) (event.getX());
          int intY = (int) (event.getY());
  
          if(event.getAction() == MotionEvent.ACTION_DOWN)
          {
              leftX = intX;
              rightX = intX;
              downY = intY;
              upY = intY;
          }
  
          Point point = new Point();
  
          point.x = intX;
          point.y = intY;
  
          if(intX &lt; leftX)
              leftX =  intX;
          if(intX &gt; rightX)
              rightX = intX;
          if(intY &gt; downY)
              downY =  intY;
          if(intY &lt; upY)
              upY = intY;
  
          points.add(point);
  
  
         invalidate();
  
          return true;
      }
  
      public void clear() 
      {       
          leftX = 0;
          rightX = 0;
          upY = 0;
          downY = 0;
  
          points.clear();
          paint.setColor(Color.WHITE);
          paint.setStyle(Style.STROKE);
          invalidate();
      }
  
  
      public Bitmap getImage2()
      {
  
      //getting the size of the new bitmap
  
          int newHeight = rightX - leftX;
          int newWidth = downY - upY;
  
          Bitmap resultingImage = Bitmap.createBitmap(newHeight, newWidth, Config.ARGB_8888);
  
          Canvas canvas = new Canvas(resultingImage);
          Paint paint = new Paint();
          paint.setAntiAlias(true);
  
          Path path = new Path();
          for (int i = 0; i &lt; points.size() - 1; i++) {
  
              path.quadTo((float)points.get(i).x, (float)points.get(i).y, (float)points.get(i+1).x, (float)points.get(i+1).y);
             // path.lineTo(points.get(i).x, points.get(i).y);
          }
  
  //closing the shape, connection last point to the first one
  
          path.quadTo((float)points.get(points.size()-1).x, (float)points.get(points.size()-1).y, (float)points.get(0).x, (float)points.get(0).y);
  
           //drawing user shape
  
          canvas.drawPath(path, paint);
  
           //getting image inside the shape
  
          paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
  
          canvas.drawBitmap(bitmapMain, 0, 0, paint);
  
          return resultingImage;
      }
  
  
  
     }
  </code></pre>
  
  <p>My activity:</p>
  
  <pre><code>public class MainActivity extends Activity implements OnClickListener {
  
      private TestView drawing;
       private static final int CAMERA_CAPTURE_IMAGE_REQUEST_CODE = 100;
       public static final int MEDIA_TYPE_IMAGE = 1;
       private static final String IMAGE_DIRECTORY_NAME = "demo pictures";
       private Uri fileUri;
  
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
  
          this.requestWindowFeature(Window.FEATURE_NO_TITLE);
  
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
  
          //drawing = (SignatureViewModed) findViewById(R.id.myTest);
          findViewById(R.id.button1).setOnClickListener(this);
          findViewById(R.id.button2).setOnClickListener(this);
          findViewById(R.id.button3).setOnClickListener(this);
  
          drawing = (TestView) findViewById(R.id.images);
  
      }
  
      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
          // Inflate the menu; this adds items to the action bar if it is present.
          getMenuInflater().inflate(R.menu.main, menu);
          return true;
      }
  
  
  
      @Override
      public void onClick(View arg0) {
          // TODO Auto-generated method stub
  
          switch(arg0.getId())
          {
  
          case R.id.button1:
          {
              drawing.clear();
              break;
          }
  
          case R.id.button2:
          {
              if(isDeviceSupportCamera())
                  captureImage();
              else
                  Toast.makeText(this, "No camera", Toast.LENGTH_SHORT).show();
              break;
          }
  
          case R.id.button3:
          {
              showCutImage();
              break;
          }
  
          }
  
      }
  
      private boolean isDeviceSupportCamera() {
          if (getApplicationContext().getPackageManager().hasSystemFeature(
                  PackageManager.FEATURE_CAMERA)) {
              // this device has a camera
              return true;
          } else {
              // no camera on this device
              return false;
          }
      }
  
      private void captureImage() {
  
          Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  
          fileUri = getOutputMediaFileUri();
  
          intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
  
          // start the image capture Intent
          startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
      }
  
      public Uri getOutputMediaFileUri() {
          return Uri.fromFile(getOutputMediaFile());
      }
  
      /**
       * returning image / video
       */
      private static File getOutputMediaFile() {
  
          // External sdcard location
          File mediaStorageDir = new File(
                  Environment
                          .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                  IMAGE_DIRECTORY_NAME);
  
          // Create the storage directory if it does not exist
          if (!mediaStorageDir.exists()) {
              if (!mediaStorageDir.mkdirs()) {
                  Log.d(IMAGE_DIRECTORY_NAME, "Oops! Failed create "
                          + IMAGE_DIRECTORY_NAME + " directory");
                  return null;
              }
          }
  
          // Create a media file name
          String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
                  Locale.getDefault()).format(new Date());
          File mediaFile;
  
           mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
  
          return mediaFile;
      }
  
      @Override
      protected void onSaveInstanceState(Bundle outState) {
          super.onSaveInstanceState(outState);
  
          // save file url in bundle as it will be null on scren orientation
          // changes
          outState.putParcelable("file_uri", fileUri);
      }
  
      @Override
      protected void onRestoreInstanceState(Bundle savedInstanceState) {
          super.onRestoreInstanceState(savedInstanceState);
  
          // get the file url
          fileUri = savedInstanceState.getParcelable("file_uri");
      }
  
  
      @Override
      protected void onActivityResult(int requestCode, int resultCode,
              Intent data2) {
  
          Bitmap bitmap = null;
  
          if (requestCode == CAMERA_CAPTURE_IMAGE_REQUEST_CODE) {
  
              if (resultCode == RESULT_OK)
              {
  
                  String filePath = fileUri.getPath();
                  bitmap = decodeSampledBitmapFromPath(filePath, true);
  
                  drawing.setBitmap(bitmap);
  
                  drawing.setImageBitmap(bitmap);
              }
  
          }
  
              super.onActivityResult(requestCode, resultCode, data2);
          }
  
      public Bitmap decodeSampledBitmapFromPath(String path, boolean isFullScreen) {
  
          Bitmap bmp = null;
          final BitmapFactory.Options options = new BitmapFactory.Options();
          options.inJustDecodeBounds = true;
  
          BitmapFactory.decodeFile(path, options);
  
          if(isFullScreen)
              options.inSampleSize = calculateInSampleSize(options, getScreenWidth() , getScreenHeight());
          else
              options.inSampleSize = calculateInSampleSize(options, 200, 200);
  
          // Decode bitmap with inSampleSize set
          options.inJustDecodeBounds = false;
          bmp = BitmapFactory.decodeFile(path, options);
  
          return bmp;
          }
  
      public int calculateInSampleSize(BitmapFactory.Options options,
              int reqWidth, int reqHeight) {
  
          final int height = options.outHeight;
          final int width = options.outWidth;
          int inSampleSize = 1;
  
          if (height &gt; reqHeight || width &gt; reqWidth) {
              if (width &gt; height) {
                  inSampleSize = Math.round((float) height / (float) reqHeight);
              } else {
                  inSampleSize = Math.round((float) width / (float) reqWidth);
               }
           }
           return inSampleSize;
          }
  
      @SuppressLint("NewApi")
      public int getScreenHeight()
      {
          Display display = ((WindowManager) this.getSystemService(WINDOW_SERVICE))
                  .getDefaultDisplay();
  
          int height = 0;
  
          if (android.os.Build.VERSION.SDK_INT &gt;= 13) {
              Point size = new Point();
              display.getSize(size);
              height = size.y;
  
          } else {
              height = display.getHeight();
  
          }
  
          return height;
      }
  
      @SuppressLint("NewApi")
      public int getScreenWidth()
      {
          Display display = ((WindowManager) this.getSystemService(WINDOW_SERVICE))
                  .getDefaultDisplay();
  
          int width = 0;
  
          if (android.os.Build.VERSION.SDK_INT &gt;= 13) {
              Point size = new Point();
              display.getSize(size);
  
              width = size.x;
          } else {
  
              width = display.getWidth();
          }
  
          return width;
      }
  
      public void showCutImage()
      {
          AlertDialog.Builder builder = new AlertDialog.Builder(this);
  
          View prefView = View.inflate(this,R.layout.image_show, null);
  
          ImageView image = (ImageView) prefView.findViewById(R.id.imageView1);
  
          image.setImageBitmap(drawing.getImage2());
  
          builder.setView(prefView);
  
          builder.show();
  
      }
  </code></pre>
  
  <p>Here is 2 pictures of my results.
  You can see the the picture I got is not the whole area I marked and its got extra corner.</p>
  
  <p><img src="https://i.stack.imgur.com/ROjez.png" alt="enter image description here"></p>
  
  <p><img src="https://i.stack.imgur.com/pnlZv.png" alt="enter image description here"></p>