Pages

Friday, October 31, 2014

Image Cropping in android : While capture image or select from gallery

Hello everyone, I write example code for capture & select image from gallery and cropping image in android. see below example code.

1. Create XML file in layout folder "res/layout/activity_main.xml".


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_select_image"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="10dp"
        android:text="Select Image" />

    <ImageView
        android:id="@+id/img_photo"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_marginTop="10dp"
        android:scaleType="fitXY" />

</LinearLayout>
2. Create XML file in layout folder "res/layout/croping_selector.xml".


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:padding="10dp" >

    <ImageView
        android:id="@+id/img_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/txt_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:text=""
        android:textColor="@android:color/black"
        android:textSize="16sp" />

</LinearLayout>

3. Create an activity Java file "MainActivity.java".


package com.limbani.imagecropping;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private final static int REQUEST_PERMISSION_REQ_CODE = 34;
        private static final int CAMERA_CODE = 101, GALLERY_CODE = 201, CROPING_CODE = 301;

        private Button btn_select_image;
        private ImageView imageView;
        private Uri mImageCaptureUri;
        private File outPutFile = null;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            outPutFile = new File(android.os.Environment.getExternalStorageDirectory(), "temp.jpg");

            btn_select_image = (Button) findViewById(R.id.btn_select_image);
            imageView = (ImageView) findViewById(R.id.img_photo);

            btn_select_image.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    selectImageOption();
                }
            });
        }

        private void selectImageOption() {
            final CharSequence[] items = { "Capture Photo", "Choose from Gallery", "Cancel" };

            AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
            builder.setTitle("Add Photo!");
            builder.setItems(items, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int item) {

                    if (items[item].equals("Capture Photo")) {

                        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                        File f = new File(android.os.Environment.getExternalStorageDirectory(), "temp1.jpg");
                        mImageCaptureUri = Uri.fromFile(f);
                        intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageCaptureUri);
                        startActivityForResult(intent, CAMERA_CODE);

                    } else if (items[item].equals("Choose from Gallery")) {

                        Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                        startActivityForResult(i, GALLERY_CODE);

                    } else if (items[item].equals("Cancel")) {
                        dialog.dismiss();
                    }
                }
            });
            builder.show();
        }

    @Override
    protected void onResume() {
        super.onResume();
        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_PERMISSION_REQ_CODE);
            return;
        }
    }

    @Override
    public void onRequestPermissionsResult(final int requestCode, final @NonNull String[] permissions, final @NonNull int[] grantResults) {
        switch (requestCode) {
            case REQUEST_PERMISSION_REQ_CODE: {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(this, "Permission granted.", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(this, "Permission denied.", Toast.LENGTH_SHORT).show();
                }
                break;
            }
        }
    }

        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {

            super.onActivityResult(requestCode, resultCode, data);

            if (requestCode == GALLERY_CODE && resultCode == RESULT_OK && null != data) {

                mImageCaptureUri = data.getData();
                System.out.println("Gallery Image URI : "+mImageCaptureUri);
                CropingIMG();

            } else if (requestCode == CAMERA_CODE && resultCode == Activity.RESULT_OK) {

                System.out.println("Camera Image URI : "+mImageCaptureUri);
                CropingIMG();
            } else if (requestCode == CROPING_CODE) {

                try {
                    if(outPutFile.exists()){
                        Bitmap photo = decodeFile(outPutFile);
                        imageView.setImageBitmap(photo);
                    }
                    else {
                        Toast.makeText(getApplicationContext(), "Error while save image", Toast.LENGTH_SHORT).show();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        private void CropingIMG() {

            final ArrayList<cropingoption> cropOptions = new ArrayList<cropingoption>();

            Intent intent = new Intent("com.android.camera.action.CROP");
            intent.setType("image/*");

            List<resolveinfo> list = getPackageManager().queryIntentActivities( intent, 0 );
            int size = list.size();
            if (size == 0) {
                Toast.makeText(this, "Cann't find image croping app", Toast.LENGTH_SHORT).show();
                return;
            } else {
                intent.setData(mImageCaptureUri);
                intent.putExtra("outputX", 512);
                intent.putExtra("outputY", 512);
                intent.putExtra("aspectX", 1);
                intent.putExtra("aspectY", 1);
                intent.putExtra("scale", true);

                //TODO: don't use return-data tag because it's not return large image data and crash not given any message
                //intent.putExtra("return-data", true);

                //Create output file here
                intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(outPutFile));

                if (size == 1) {
                    Intent i   = new Intent(intent);
                    ResolveInfo res = (ResolveInfo) list.get(0);

                    i.setComponent( new ComponentName(res.activityInfo.packageName, res.activityInfo.name));

                    startActivityForResult(i, CROPING_CODE);
                } else {
                    for (ResolveInfo res : list) {
                        final CropingOption co = new CropingOption();

                        co.title  = getPackageManager().getApplicationLabel(res.activityInfo.applicationInfo);
                        co.icon  = getPackageManager().getApplicationIcon(res.activityInfo.applicationInfo);
                        co.appIntent= new Intent(intent);
                        co.appIntent.setComponent( new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
                        cropOptions.add(co);
                    }

                    CropingOptionAdapter adapter = new CropingOptionAdapter(getApplicationContext(), cropOptions);

                    AlertDialog.Builder builder = new AlertDialog.Builder(this);
                    builder.setTitle("Choose Croping App");
                    builder.setCancelable(false);
                    builder.setAdapter( adapter, new DialogInterface.OnClickListener() {
                        public void onClick( DialogInterface dialog, int item ) {
                            startActivityForResult( cropOptions.get(item).appIntent, CROPING_CODE);
                        }
                    });

                    builder.setOnCancelListener( new DialogInterface.OnCancelListener() {
                        @Override
                        public void onCancel( DialogInterface dialog ) {

                            if (mImageCaptureUri != null ) {
                                getContentResolver().delete(mImageCaptureUri, null, null );
                                mImageCaptureUri = null;
                            }
                        }
                    } );

                    AlertDialog alert = builder.create();
                    alert.show();
                }
            }
        }

        private Bitmap decodeFile(File f) {
            try {
                // decode image size
                BitmapFactory.Options o = new BitmapFactory.Options();
                o.inJustDecodeBounds = true;
                BitmapFactory.decodeStream(new FileInputStream(f), null, o);

                // Find the correct scale value. It should be the power of 2.
                final int REQUIRED_SIZE = 512;
                int width_tmp = o.outWidth, height_tmp = o.outHeight;
                int scale = 1;
                while (true) {
                    if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE)
                        break;
                    width_tmp /= 2;
                    height_tmp /= 2;
                    scale *= 2;
                }

                // decode with inSampleSize
                BitmapFactory.Options o2 = new BitmapFactory.Options();
                o2.inSampleSize = scale;
                return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
            } catch (FileNotFoundException e) {
            }
            return null;
        }
    }


4. Create Java file "CropingOption.java"


package com.limbani.imagecropping;

import android.content.Intent;
import android.graphics.drawable.Drawable;

public class CropingOption {
    public CharSequence title;
    public Drawable icon;
    public Intent appIntent;
}

5. Create Java file "CropingOptionAdapter.java"


package com.limbani.imagecropping;

import java.util.ArrayList;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class CropingOptionAdapter extends ArrayAdapter {
    private ArrayList mOptions;
    private LayoutInflater mInflater;

    public CropingOptionAdapter(Context context, ArrayList options) {
        super(context, R.layout.croping_selector, options);

        mOptions  = options;

        mInflater = LayoutInflater.from(context);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup group) {
        if (convertView == null)
            convertView = mInflater.inflate(R.layout.croping_selector, null);

        CropingOption item = (CropingOption) mOptions.get(position);

        if (item != null) {
            ((ImageView) convertView.findViewById(R.id.img_icon)).setImageDrawable(item.icon);
            ((TextView) convertView.findViewById(R.id.txt_name)).setText(item.title);

            return convertView;
        }

        return null;
    }
}

6. Add your activity class and user permission in "AndroidManifest.xml".


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.limbani.imagecropping">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


7. ScreenShot".







Thanks :)
Download Code

19 comments:

  1. There are lot of format errors in this sample :(
    Can you share the source files if you dont mind.

    ReplyDelete
    Replies
    1. Hey, can you please tell me if you have found solutions....

      Delete
    2. hey, can you please tell me if you have found solution, Thanks

      Delete
  2. There are code in many problems. can you solve and update it.?

    ReplyDelete
  3. No problem for me.Thank u very much

    ReplyDelete
  4. No problem for me. It working. Thank u

    ReplyDelete
    Replies
    1. Intent is not working in the main activity.I startactivity on OnActivityResult.Please help me

      Delete
  5. Change line, in MainActivity
    ---------------------------
    //

    ArrayList list= (ArrayList)getPackageManager().queryIntentActivities( intent,0);

    instead of

    List list=getPackageManager().queryIntentActivities( intent,0);

    //
    CropingOption co =new CropingOption();
    co=(CropingOption)cropOptions.get(item);
    startActivityForResult(co.appIntent, CROPING_CODE);

    instead of

    startActivityForResult(cropOptions.get(item).appIntent, CROPING_CODE);

    ------------------------------

    Change line in , CropOptionAdapter
    ----------------------------------------------

    CropingOption item = (CropingOption) mOptions.get(position);

    instead of

    CropingOption item = mOptions.get(position);

    ReplyDelete
    Replies
    1. Hello,
      I updated my post check it.

      Delete
    2. This code is not working in android 5. when select picture from gellery and picture croped the app is crashed.....

      Delete
  6. It works well for me. Thanks a lot.

    ReplyDelete
  7. How to use the same code for more than one imageview?

    ReplyDelete
  8. There are lot of error in this code.... this code is not working on android5

    ReplyDelete
    Replies
    1. Hello,
      In Which device Are you testing?
      Please send error so can fix that.

      Also I have tested this code in Android7 that's working fine.

      Delete
  9. Hi Durgesh!Thanks for this awesome tutorial.It works fine on Nougat and Kitkat. But in 5.1.0 it throws the exception-"Can't find image cropping app".Is there any solution dude?

    ReplyDelete
  10. working for me sir can you please tell me how to upload that image to the server ,I mean where to write the logic for that

    ReplyDelete