Android fingercrop image tutorial

In this tutorial we will learn how to implement finger crop to an image in ImageView and how to resize the ImageView to the cropped image size. This example will have a CropActivity which will have an ImageView which allows cropping and a button which will save the cropped image.

If you find the tutorial useful please subscribe to our youtube channel

There will be an arraylist which will store the x,y coordinates which is used for calculating width and height of cropped image. Let us start by creating a model class which will help to store x,y coordinates. Create a file under java/your-package/

CropModel.java

public class CropModel {
float x;
float y;

public CropModel(float y, float x) {
this.y = y;
this.x = x;
}

public float getY() {
return y;
}

public void setY(float y) {
this.y = y;
}

public float getX() {
return x;
}

public void setX(float x) {
this.x = x;
}
}

Now create an Activity CropActivity.java with layout activity_crop.xml and use the following codes

activity_crop.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="#FFFFFF">


<ImageView
android:id="@+id/im_crop_image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="#C0C0C0" />

<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#C0C0C0"
android:layout_above="@+id/ll_button"
></View>

<Button
android:id="@+id/btn_ok"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@color/colorPrimary"
android:textColor="#FFFFFF"
android:text="OK"/>

</RelativeLayout>

CropActivity.java

public class CropActivity extends AppCompatActivity implements OnTouchListener, View.OnClickListener {
ImageView im_crop_image_view;
Path clipPath;
Bitmap bmp;
Bitmap alteredBitmap;
Canvas canvas;
Paint paint;
float downx = 0;
float downy = 0;
float tdownx = 0;
float tdowny = 0;
float upx = 0;
float upy = 0;
long lastTouchDown = 0;
int CLICK_ACTION_THRESHHOLD = 100;
Display display;
Point size;
int screen_width,screen_height;
Button btn_ok;
ArrayList<CropModel> cropModelArrayList;
float smallx,smally,largex,largey;
Paint cpaint;
Bitmap temporary_bitmap;
private ProgressDialog pDialog;

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_crop);


init();

if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
Window window = this.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.setStatusBarColor(this.getResources().getColor(R.color.colorPrimaryDark));
}

int cx = (screen_width - bmp.getWidth()) >> 1;
int cy = (screen_height - bmp.getHeight()) >> 1;
canvas.drawBitmap(bmp, cx, cy, null);
im_crop_image_view.setImageBitmap(alteredBitmap);
im_crop_image_view.setOnTouchListener(this);
}

private void init() {

pDialog = new ProgressDialog(CropActivity.this);
im_crop_image_view = (ImageView) findViewById(R.id.im_crop_image_view);
cropModelArrayList = new ArrayList<>();
btn_ok = (Button) findViewById(R.id.btn_ok);
btn_ok.setOnClickListener(this);
display = getWindowManager().getDefaultDisplay();
size = new Point();
display.getSize(size);
screen_width = size.x;
screen_height = size.y;

initcanvas();
}

public void initcanvas() {

Drawable d = getResources().getDrawable(R.drawable.sample);
bmp = ((BitmapDrawable)d).getBitmap();

alteredBitmap = Bitmap.createBitmap(screen_width, screen_height, bmp.getConfig());
canvas = new Canvas(alteredBitmap);
paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
paint.setPathEffect(new DashPathEffect(new float[]{15.0f, 15.0f}, 0));

}

public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();

switch (action) {
case MotionEvent.ACTION_DOWN:


downx = event.getX();
downy = event.getY();
clipPath = new Path();
clipPath.moveTo(downx, downy);
tdownx = downx;
tdowny = downy;
smallx = downx;
smally = downy;
largex = downx;
largey = downy;
lastTouchDown = System.currentTimeMillis();
break;

case MotionEvent.ACTION_MOVE:
upx = event.getX();
upy = event.getY();
cropModelArrayList.add(new CropModel(upx, upy));
clipPath = new Path();
clipPath.moveTo(tdownx,tdowny);
for(int i = 0; i<cropModelArrayList.size();i++){
clipPath.lineTo(cropModelArrayList.get(i).getY(),cropModelArrayList.get(i).getX());
}
canvas.drawPath(clipPath, paint);
im_crop_image_view.invalidate();
downx = upx;
downy = upy;
break;
case MotionEvent.ACTION_UP:
if (System.currentTimeMillis() - lastTouchDown < CLICK_ACTION_THRESHHOLD) {

cropModelArrayList.clear();
initcanvas();

int cx = (screen_width - bmp.getWidth()) >> 1;
int cy = (screen_height - bmp.getHeight()) >> 1;
canvas.drawBitmap(bmp, cx, cy, null);
im_crop_image_view.setImageBitmap(alteredBitmap);

} else {
if (upx != upy) {
upx = event.getX();
upy = event.getY();


canvas.drawLine(downx, downy, upx, upy, paint);
clipPath.lineTo(upx, upy);
im_crop_image_view.invalidate();

crop();
}

}
break;
case MotionEvent.ACTION_CANCEL:
break;
default:
break;
}
return true;
}

public void crop() {

clipPath.close();
clipPath.setFillType(FillType.INVERSE_WINDING);

for(int i = 0; i<cropModelArrayList.size();i++){
if(cropModelArrayList.get(i).getY()<smallx){

smallx=cropModelArrayList.get(i).getY();
}
if(cropModelArrayList.get(i).getX()<smally){

smally=cropModelArrayList.get(i).getX();
}
if(cropModelArrayList.get(i).getY()>largex){

largex=cropModelArrayList.get(i).getY();
}
if(cropModelArrayList.get(i).getX()>largey){

largey=cropModelArrayList.get(i).getX();
}
}

temporary_bitmap = alteredBitmap;
cpaint = new Paint();
cpaint.setAntiAlias(true);
cpaint.setColor(getResources().getColor(R.color.colorAccent));
cpaint.setAlpha(100);
canvas.drawPath(clipPath, cpaint);

canvas.drawBitmap(temporary_bitmap, 0, 0, cpaint);

}

@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_ok:
save();

default:
break;
}

}


private void save() {

if(clipPath != null) {
final int color = 0xff424242;
final Paint paint = new Paint();
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawPath(clipPath, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

canvas.drawBitmap(alteredBitmap, 0, 0, paint);

float w = largex - smallx;
float h = largey - smally;
alteredBitmap = Bitmap.createBitmap(alteredBitmap, (int) smallx, (int) smally, (int) w, (int) h);

}else{
alteredBitmap = bmp;
}
pDialog.show();

Thread mThread = new Thread() {
@Override
public void run() {

Bitmap bitmap = alteredBitmap;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 70, stream);
byte[] byteArray = stream.toByteArray();
pDialog.dismiss();

Intent intent = new Intent(CropActivity.this, DisplayCropActivity.class);
intent.putExtra("image",byteArray);
startActivity(intent);
}
};
mThread.start();

}


}

In the above  activity after clicking save button It will do the crop operation and will create a bitmap of cropped image. Now let us create another activity DisplayCropActivity to display cropped image

Add the following imageview layout to DisplayCropActivity ‘s layout

<ImageView
android:id="@+id/im_crop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"/>

Now use the following code in your DisplayCropActivity.java

ImageView im_crop = (ImageView) findViewById(R.id.im_crop);
byte[] byteArray = getIntent().getByteArrayExtra("image");
Bitmap bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
im_crop.setImageBitmap(bmp);

Now run the code you will get the following output

fingercrop-android
fingercrop-android

About the author

Hi guys, i am the author of codesfor. I am a B.Tech graduate currently working as an App developer. Apart from job i am a blogger and a freelancer.

29 Comments

  1. Sandro November 20, 2018 Reply
    • sumit December 6, 2018 Reply

Add a Comment

Your email address will not be published. Required fields are marked *