Android Open Source - ImageCropper Crop Window






From Project

Back to project page ImageCropper.

License

The source code is released under:

Apache License

If you think the Android project ImageCropper listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 *  COPYRIGHT NOTICE  /*  ww  w. j a  v  a  2 s .c  om*/
 *  Copyright (C) 2015, ticktick <lujun.hust@gmail.com>
 *  http://ticktick.blog.51cto.com/
 *   
 *  @license under the Apache License, Version 2.0 
 *
 *  @file    CropWindow.java
 *  @brief   Manage the position and size of crop window
 *  
 *  @version 1.0     
 *  @author  ticktick
 *  @date    2015/01/09    
 */
package com.ticktick.imagecropper;

import com.ticktick.imagecropper.CropImageActivity.CropParam;

import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;

public class CropWindow {
  
    private static final int TOUCH_NONE             = (1 << 0);
    private static final int TOUCH_GROW_LEFT_EDGE   = (1 << 1);
    private static final int TOUCH_GROW_RIGHT_EDGE  = (1 << 2);
    private static final int TOUCH_GROW_TOP_EDGE    = (1 << 3);
    private static final int TOUCH_GROW_BOTTOM_EDGE = (1 << 4);
    private static final int TOUCH_MOVE_WINDOW      = (1 << 5);
  
    private static final float BORDER_THRESHOLD   = 30f;    
    private static final float DEFAULT_MIN_WDITH  = 30f;
    private static final float DEFAULT_MIN_HEIGHT = 30f;
    
    private float mLeft;
    private float mTop;  
    private float mWidth;
    private float mHeight;  
    private RectF mImageRect;
    private CropParam mCropParam;
    private int mTouchMode = TOUCH_NONE;    
    
    public CropWindow( RectF imageRect, CropParam params ) {
    
        mWidth  = Math.min(imageRect.width(),imageRect.height())*4/5;
        mHeight = mWidth;
    
        if( params.mOutputX != 0 && params.mOutputY != 0 ) {
            mWidth  = params.mOutputX;
            mHeight = params.mOutputY;
        }
        else {      
            if( params.mMaxOutputX != 0 && params.mMaxOutputY !=0 ) {
                mWidth  = params.mMaxOutputX; 
                mHeight = params.mMaxOutputY;
            }
            if( params.mAspectX != 0 && params.mAspectY != 0 ) {
                if( params.mAspectX > params.mAspectY ) {
                    mHeight = mWidth*params.mAspectY/params.mAspectX;
                }
                else {
                    mWidth = mHeight*params.mAspectX/params.mAspectY;
                }
           }      
       }  
    
       mLeft = imageRect.left + (imageRect.width()-mWidth)/2;
       mTop  = imageRect.top  + (imageRect.height()-mHeight)/2; ;
       mImageRect = imageRect;
       mCropParam = params;
    }
  
    public float left() {
        return mLeft; 
    }
  
    public float right() {
        return (mLeft+mWidth);
    }
  
    public float top() {
        return mTop;
    }
  
    public float bottom() {
        return (mTop+mHeight);
    }
  
    public float width() {
        return mWidth;
    }
  
    public float height() {
        return mHeight;        
    }
  
    public Rect getWindowRect() {
        return new Rect((int)left(), (int)top(), (int)right(), (int)bottom());
    }
  
    public RectF getWindowRectF() {
        return new RectF(left(), top(), right(), bottom());
    }
  
    public Rect getWindowRect( float scale ) {
  int width   = (int)(width()/scale);
  int height  = (int)(height()/scale);
  int xoffset = (int)((left()-mImageRect.left)/scale);
  int yoffset = (int)((top()-mImageRect.top)/scale);
  return new Rect(xoffset,yoffset,xoffset+width,yoffset+height);
    }
  
    public RectF[] getOutWindowRects() {
  RectF[] rects = new RectF[4];
  Rect window = getWindowRect();
  rects[0] = new RectF(mImageRect.left,mImageRect.top,mImageRect.right,window.top);
  rects[1] = new RectF(mImageRect.left,window.top,window.left,window.bottom);
  rects[2] = new RectF(window.right,window.top,mImageRect.right,window.bottom);
  rects[3] = new RectF(mImageRect.left,window.bottom,mImageRect.right,mImageRect.bottom);
  return rects;
    }
  
    public Point[] getDragPoints() {
  Point[] points = new Point[4];
        Rect window = getWindowRect();      
        points[0] = new Point(window.left,window.centerY());   //Left
        points[1] = new Point(window.centerX(),window.top);    //Top
        points[2] = new Point(window.right,window.centerY());  //Right
        points[3] = new Point(window.centerX(),window.bottom); //Bottom
        return points;
    }
  
    //By default, the border equals the image border
    private RectF getGrowBorder() {    
  RectF border = new RectF(mImageRect);
  if( mCropParam.mMaxOutputX != 0 ) {
            border.left  = Math.max(right()-mCropParam.mMaxOutputX,mImageRect.left);
            border.right = Math.min(left()+mCropParam.mMaxOutputX,mImageRect.right);
  }
  if( mCropParam.mMaxOutputY != 0 ) {
            border.top = Math.max(bottom()-mCropParam.mMaxOutputY,mImageRect.top);
            border.bottom = Math.min(top()+mCropParam.mMaxOutputY,mImageRect.bottom);
  }
  return border;
    }
  
    //Make sure the crop window inside the border
    private void adjustWindowRect() {  
  mLeft = (left() < mImageRect.left) ? mImageRect.left : left();
  mLeft = (right() >= mImageRect.right) ? mImageRect.right-mWidth : left();
  mTop  = (top() < mImageRect.top) ? mImageRect.top : top();
  mTop  = (bottom() >= mImageRect.bottom) ? mImageRect.bottom-mHeight : top();
    }
  
    public boolean onTouchDown( float x, float y ) {
    
  RectF window = getWindowRectF();
  
  //IF set output X&Y, forbid change the crop window size
  if( mCropParam.mOutputX == 0 && mCropParam.mOutputY == 0 ) {

            //make sure the position is between the top and the bottom edge (with some tolerance). Similar for isYinWindow.
            boolean isXinWindow = (x >= window.left - BORDER_THRESHOLD) && (x < window.right  + BORDER_THRESHOLD);
            boolean isYinWindow = (y >= window.top  - BORDER_THRESHOLD) && (y < window.bottom + BORDER_THRESHOLD);        
        
            // Check whether the position is near some edge(s)
            if( (Math.abs(window.left - x) < BORDER_THRESHOLD) && isYinWindow ) {
          mTouchMode |= TOUCH_GROW_LEFT_EDGE;
            }
            if( (Math.abs(window.right - x) < BORDER_THRESHOLD) && isYinWindow ) {
           mTouchMode |= TOUCH_GROW_RIGHT_EDGE;
            }
            if( (Math.abs(window.top - y) < BORDER_THRESHOLD) && isXinWindow) {
          mTouchMode |= TOUCH_GROW_TOP_EDGE;
            }
            if( (Math.abs(window.bottom - y) < BORDER_THRESHOLD) && isXinWindow) {
          mTouchMode |= TOUCH_GROW_BOTTOM_EDGE;
            }
  }
    
        // Not near any edge but inside the rectangle: move
        if (mTouchMode == TOUCH_NONE && window.contains((int)x,(int)y)) {
            mTouchMode = TOUCH_MOVE_WINDOW;        
        }
        
        return mTouchMode!=TOUCH_NONE;
    }
  
    public boolean onTouchUp() {
  mTouchMode = TOUCH_NONE;
  return true;
    }

    public boolean onTouchMoved( float deltaX, float deltaY ) {
      
  if( mTouchMode == TOUCH_NONE ) {
            return false;
  }
  
  if( mTouchMode == TOUCH_MOVE_WINDOW ) {      
            mLeft += deltaX;            
            mTop  += deltaY;      
            adjustWindowRect();
  }    
  else {
    
            //IF set output X&Y, forbid change the crop window size
            if( mCropParam.mOutputX != 0 && mCropParam.mOutputY != 0 ) {
                return false;
            }
    
            //IF set x:y aspect, only support drag from right&bottom
            if( mCropParam.mAspectX != 0 && mCropParam.mAspectY != 0 ) {
    if( (TOUCH_GROW_RIGHT_EDGE & mTouchMode ) == 0 || (TOUCH_GROW_BOTTOM_EDGE & mTouchMode ) == 0 ) {
      return false;
    }        
    float min_scale = Math.max(DEFAULT_MIN_WDITH/mWidth,DEFAULT_MIN_HEIGHT/mHeight);
    RectF border = getGrowBorder();
    float max_right_scale  = (border.right-left())/width();
    float max_bottom_scale = (border.bottom-top())/height();
    float right_scale  = (width()+deltaX)/width();
    float bottom_scale = (height()+deltaY)/height();
    float scale = Math.min(Math.min(right_scale,max_right_scale), Math.min(bottom_scale,max_bottom_scale));                        
    mWidth  = mWidth*Math.max(scale,min_scale);    
    mHeight = mHeight*Math.max(scale,min_scale);
    return true;
            }
  
            RectF window = getWindowRectF();
            RectF border = getGrowBorder();
  
            if( (TOUCH_GROW_LEFT_EDGE & mTouchMode) != 0 ) {
    window.left += deltaX;  
    window.left = (window.left < border.left) ? border.left : window.left;
    window.left = (window.left > window.right-DEFAULT_MIN_WDITH) ? window.right-DEFAULT_MIN_WDITH : window.left;        
            }      
            if( (TOUCH_GROW_RIGHT_EDGE & mTouchMode ) != 0 ) {
    window.right += deltaX;
    window.right = (window.right > border.right) ? border.right : window.right;
    window.right = (window.right < window.left+DEFAULT_MIN_WDITH) ? window.left+DEFAULT_MIN_WDITH : window.right;
            }
            if( (TOUCH_GROW_TOP_EDGE & mTouchMode ) != 0 ) {
    window.top += deltaY;
    window.top = (window.top < border.top) ? border.top : window.top;
    window.top = (window.top > window.bottom-DEFAULT_MIN_HEIGHT) ? window.bottom-DEFAULT_MIN_HEIGHT : window.top;        
            }
            if( (TOUCH_GROW_BOTTOM_EDGE & mTouchMode ) != 0 ) {
                window.bottom += deltaY;
                window.bottom = (window.bottom > border.bottom) ? border.bottom : window.bottom;
                window.bottom = (window.bottom < window.top+DEFAULT_MIN_HEIGHT) ? window.top+DEFAULT_MIN_HEIGHT : window.bottom;
            }
    
            mLeft = window.left;
            mTop  = window.top;
    
            mWidth  = window.right - window.left;    
            mHeight = window.bottom - window.top;
  }    
  
  return true;
    }
}




Java Source Code List

com.ticktick.imagecropper.CropImageActivity.java
com.ticktick.imagecropper.CropImageView.java
com.ticktick.imagecropper.CropIntent.java
com.ticktick.imagecropper.CropWindow.java
com.ticktick.imagecropper.RotateBitmap.java
com.ticktick.imagecropper.TouchEventDetector.java
com.ticktick.testimagecropper.MainActivity.java