ArthurHub / Android-Image-Cropper

Image Cropping Library for Android, optimized for Camera / Gallery.
Apache License 2.0
6.39k stars 1.36k forks source link

How to save image to gallery #27

Closed mayurxd closed 8 years ago

mayurxd commented 8 years ago

after croping and rotaing how to save image into gallery in the new folder

dharmeshmp commented 8 years ago

First implement

CropImageView.OnGetCroppedImageCompleteListener

and set listener

mCropImageView.setOnGetCroppedImageCompleteListener(this);

You can call

mCropImageView.getCroppedImageAsync(mCropImageView.getCropShape(), 0, 0);

method and than you can get callback in this method.

@Override
    public void onGetCroppedImageComplete(CropImageView view, Bitmap bitmap, Exception error) {
        if (error == null) {
           storeImage(bitmap);
        } else {
            //Error
        }
    }

Store Image


private void storeImage(Bitmap image) {
    File pictureFile = getOutputMediaFile();
    if (pictureFile == null) {
        Log.d(TAG,
                "Error creating media file, check storage permissions: ");// e.getMessage());
        return;
    } 
    try {
        FileOutputStream fos = new FileOutputStream(pictureFile);
        image.compress(Bitmap.CompressFormat.PNG, 90, fos);
        fos.close();
    } catch (FileNotFoundException e) {
        Log.d(TAG, "File not found: " + e.getMessage());
    } catch (IOException e) {
        Log.d(TAG, "Error accessing file: " + e.getMessage());
    }  
}

To Get the Path for Image Storage

private  File getOutputMediaFile(){
    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this. 
    File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
            + "/Android/data/"
            + getApplicationContext().getPackageName()
            + "/Files"); 

    // This location works best if you want the created images to be shared
    // between applications and persist after your app has been uninstalled.

    // Create the storage directory if it does not exist
    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            return null;
        }
    } 
    // Create a media file name
    String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmm").format(new Date());
    File mediaFile;
        String mImageName="MI_"+ timeStamp +".jpg";
        mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName);  
    return mediaFile;
} 

http://stackoverflow.com/a/15662384/2803774

mayurxd commented 8 years ago

i am getting errors

1) At app launch i am getting error as :- image crop failed width must be >0

2)App is now unstable and forced closing sometimes, showing this errors in logcat

02-08 18:39:43.434 15295-15295/com.example.croppersample E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.croppersample, PID: 15295 java.lang.NullPointerException at com.theartofdev.edmodo.cropper.sample.MainActivity.storeImage(MainActivity.java:256) at com.theartofdev.edmodo.cropper.sample.MainActivity.onGetCroppedImageComplete(MainActivity.java:333) at com.theartofdev.edmodo.cropper.CropImageView.onGetImageCroppingAsyncComplete(CropImageView.java:663) at com.theartofdev.edmodo.cropper.BitmapCroppingWorkerTask.onPostExecute(BitmapCroppingWorkerTask.java:154) at com.theartofdev.edmodo.cropper.BitmapCroppingWorkerTask.onPostExecute(BitmapCroppingWorkerTask.java:26) at android.os.AsyncTask.finish(AsyncTask.java:632) at android.os.AsyncTask.access$600(AsyncTask.java:177) at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5146) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:732) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:566) at dalvik.system.NativeStart.main(Native Method)

here is my main activity

public class MainActivity extends Activity implements CropImageView.OnSetImageUriCompleteListener, CropImageView.OnGetCroppedImageCompleteListener {

//region: Fields and Consts

private static final int DEFAULT_ASPECT_RATIO_VALUES = 20;

private static final int ROTATE_NINETY_DEGREES = 90;

private static final String ASPECT_RATIO_X = "ASPECT_RATIO_X";

private static final String ASPECT_RATIO_Y = "ASPECT_RATIO_Y";

private static final int ON_TOUCH = 1;

private CropImageView mCropImageView;

private int mAspectRatioX = DEFAULT_ASPECT_RATIO_VALUES;

private int mAspectRatioY = DEFAULT_ASPECT_RATIO_VALUES;

Bitmap croppedImage;
//endregion

// Saves the state upon rotating the screen/restarting the activity
@Override
protected void onSaveInstanceState(@SuppressWarnings("NullableProblems") Bundle bundle) {
    super.onSaveInstanceState(bundle);
    bundle.putInt(ASPECT_RATIO_X, mAspectRatioX);
    bundle.putInt(ASPECT_RATIO_Y, mAspectRatioY);
}

// Restores the state upon rotating the screen/restarting the activity
@Override
protected void onRestoreInstanceState(@SuppressWarnings("NullableProblems") Bundle bundle) {
    super.onRestoreInstanceState(bundle);
    mAspectRatioX = bundle.getInt(ASPECT_RATIO_X);
    mAspectRatioY = bundle.getInt(ASPECT_RATIO_Y);
}

public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    this.requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.activity_main);

    // Initialize components of the app
    mCropImageView = (CropImageView) findViewById(R.id.CropImageView);
    final SeekBar aspectRatioXSeek = (SeekBar) findViewById(R.id.aspectRatioXSeek);
    final SeekBar aspectRatioYSeek = (SeekBar) findViewById(R.id.aspectRatioYSeek);
    Spinner showGuidelinesSpin = (Spinner) findViewById(R.id.showGuidelinesSpin);
    final TextView aspectRatioNum = (TextView) findViewById(R.id.aspectRatioNum);

    if (savedInstanceState == null) {
        mCropImageView.setImageResource(R.drawable.butterfly);
    }

    // Sets sliders to be disabled until fixedAspectRatio is set
    aspectRatioXSeek.setEnabled(false);
    aspectRatioYSeek.setEnabled(false);

    // Set initial spinner value
    showGuidelinesSpin.setSelection(ON_TOUCH);

    //Sets the rotate button
    final Button rotateButton = (Button) findViewById(R.id.Button_rotate);
    rotateButton.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            mCropImageView.rotateImage(ROTATE_NINETY_DEGREES);
        }
    });

    // Sets fixedAspectRatio
    ((ToggleButton) findViewById(R.id.fixedAspectRatioToggle)).setOnCheckedChangeListener(new OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            mCropImageView.setFixedAspectRatio(isChecked);
            if (isChecked) {
                aspectRatioXSeek.setEnabled(true);
                aspectRatioYSeek.setEnabled(true);
            } else {
                aspectRatioXSeek.setEnabled(false);
                aspectRatioYSeek.setEnabled(false);
            }
        }
    });

    // Sets crop shape
    ((ToggleButton) findViewById(R.id.cropShapeToggle)).setOnCheckedChangeListener(new OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            mCropImageView.setCropShape(isChecked ? CropImageView.CropShape.OVAL : CropImageView.CropShape.RECTANGLE);
        }
    });

    // Sets initial aspect ratio to 10/10, for demonstration purposes
    mCropImageView.setAspectRatio(DEFAULT_ASPECT_RATIO_VALUES, DEFAULT_ASPECT_RATIO_VALUES);

    aspectRatioXSeek.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar aspectRatioXSeek, int progress, boolean fromUser) {
            mAspectRatioX = Math.max(1, progress);
            mCropImageView.setAspectRatio(mAspectRatioX, mAspectRatioY);
            aspectRatioNum.setText("(" + mAspectRatioX + ", " + mAspectRatioY + ")");
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
        }
    });

    aspectRatioYSeek.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar aspectRatioYSeek, int progress, boolean fromUser) {
            mAspectRatioY = Math.max(1, progress);
            mCropImageView.setAspectRatio(mAspectRatioX, mAspectRatioY);
            aspectRatioNum.setText("(" + mAspectRatioX + ", " + mAspectRatioY + ")");
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
        }
    });

    // Sets up the Spinner
    showGuidelinesSpin.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
            switch (i) {
                case 0:
                    mCropImageView.setGuidelines(CropImageView.Guidelines.OFF);
                    break;
                case 1:
                    mCropImageView.setGuidelines(CropImageView.Guidelines.ON_TOUCH);
                    break;
                case 2:
                    mCropImageView.setGuidelines(CropImageView.Guidelines.ON);
                    break;
            }
        }

        public void onNothingSelected(AdapterView<?> adapterView) {
            return;
        }
    });

    final TextView snapRadiusNum = (TextView) findViewById(R.id.snapRadiusNum);
    ((SeekBar) findViewById(R.id.snapRadiusSeek)).setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            mCropImageView.setSnapRadius(progress);
            snapRadiusNum.setText(Integer.toString(progress));
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

        }
    });

    findViewById(R.id.Button_crop).setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            mCropImageView.getCroppedImageAsync(mCropImageView.getCropShape(), 0, 0);
        }
    });

    findViewById(R.id.Button_load).setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            startActivityForResult(getPickImageChooserIntent(), 200);
        }
    });

    mCropImageView.setOnGetCroppedImageCompleteListener(this);
    mCropImageView.getCroppedImageAsync(mCropImageView.getCropShape(), 0, 0);

}

static final String TAG = "YOUR-TAG-NAME";
private void storeImage(Bitmap image) {
    File pictureFile = getOutputMediaFile();
    if (pictureFile == null) {
        Log.d(TAG,
                "Error creating media file, check storage permissions: ");// e.getMessage());
        return;
    }
    try {
        FileOutputStream fos = new FileOutputStream(pictureFile);
        image.compress(Bitmap.CompressFormat.PNG, 90, fos);
        fos.close();
    } catch (FileNotFoundException e) {
        Log.d(TAG, "File not found: " + e.getMessage());
    } catch (IOException e) {
        Log.d(TAG, "Error accessing file: " + e.getMessage());
    }
}

private  File getOutputMediaFile(){
    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this.
    File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
            + "/Android/data/"
            + getApplicationContext().getPackageName()
            + "/Files");

    // This location works best if you want the created images to be shared
    // between applications and persist after your app has been uninstalled.

    // Create the storage directory if it does not exist
    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            return null;
        }
    }
    // Create a media file name
    String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmm").format(new Date());
    File mediaFile;
    String mImageName="MI_"+ timeStamp +".jpg";
    mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName);
    return mediaFile;
}

@Override
protected void onStart() {
    super.onStart();
    mCropImageView.setOnSetImageUriCompleteListener(this);
    mCropImageView.setOnGetCroppedImageCompleteListener(this);
}

@Override
protected void onStop() {
    super.onStop();
    mCropImageView.setOnSetImageUriCompleteListener(null);
    mCropImageView.setOnGetCroppedImageCompleteListener(null);
}

@Override
public void onSetImageUriComplete(CropImageView view, Uri uri, Exception error) {
    if (error == null) {
        Toast.makeText(mCropImageView.getContext(), "Image load successful", Toast.LENGTH_SHORT).show();
    } else {
        Toast.makeText(mCropImageView.getContext(), "Image load failed: " + error.getMessage(), Toast.LENGTH_LONG).show();
    }
}

@Override
public void onGetCroppedImageComplete(CropImageView view, Bitmap bitmap, Exception error) {
    if (error == null) {
        croppedImage = bitmap;
        ImageView croppedImageView = (ImageView) findViewById(R.id.croppedImageView);
        croppedImageView.setImageBitmap(croppedImage);

      //CapturePhotoUtils cp;
        //cp.insertImage(bitmap,"","");

    } else {
        Toast.makeText(mCropImageView.getContext(), "Image crop failed: " + error.getMessage(), Toast.LENGTH_LONG).show();
    }

    if (error == null) {
        storeImage(bitmap);
    } else {
        //Error
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == Activity.RESULT_OK) {
        Uri imageUri = getPickImageResultUri(data);
        ((CropImageView) findViewById(R.id.CropImageView)).setImageUriAsync(imageUri);

    }
}

/**
 * Create a chooser intent to select the source to get image from.<br/>
 * The source can be camera's (ACTION_IMAGE_CAPTURE) or gallery's (ACTION_GET_CONTENT).<br/>
 * All possible sources are added to the intent chooser.
 */
public Intent getPickImageChooserIntent() {

    // Determine Uri of camera image to save.
    Uri outputFileUri = getCaptureImageOutputUri();

    List<Intent> allIntents = new ArrayList<>();
    PackageManager packageManager = getPackageManager();

    // collect all camera intents
    Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
    for (ResolveInfo res : listCam) {
        Intent intent = new Intent(captureIntent);
        intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
        intent.setPackage(res.activityInfo.packageName);
        if (outputFileUri != null) {
            intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
        }
        allIntents.add(intent);
    }

    // collect all gallery intents
    Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT);
    galleryIntent.setType("image/*");
    List<ResolveInfo> listGallery = packageManager.queryIntentActivities(galleryIntent, 0);
    for (ResolveInfo res : listGallery) {
        Intent intent = new Intent(galleryIntent);
        intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
        intent.setPackage(res.activityInfo.packageName);
        allIntents.add(intent);
    }

    // the main intent is the last in the list (fucking android) so pickup the useless one
    Intent mainIntent = allIntents.get(allIntents.size() - 1);
    for (Intent intent : allIntents) {
        if (intent.getComponent().getClassName().equals("com.android.documentsui.DocumentsActivity")) {
            mainIntent = intent;
            break;
        }
    }
    allIntents.remove(mainIntent);

    // Create a chooser from the main intent
    Intent chooserIntent = Intent.createChooser(mainIntent, "Select source");

    // Add all other intents
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, allIntents.toArray(new Parcelable[allIntents.size()]));

    return chooserIntent;
}

/**
 * Get URI to image received from capture by camera.
 */
private Uri getCaptureImageOutputUri() {
    Uri outputFileUri = null;
    File getImage = getExternalCacheDir();
    if (getImage != null) {
        outputFileUri = Uri.fromFile(new File(getImage.getPath(), "pickImageResult.jpeg"));
    }
    return outputFileUri;
}

/**
 * Get the URI of the selected image from {@link #getPickImageChooserIntent()}.<br/>
 * Will return the correct URI for camera and gallery image.
 *
 * @param data the returned data of the activity result
 */
public Uri getPickImageResultUri(Intent data) {
    boolean isCamera = true;
    if (data != null) {
        String action = data.getAction();
        isCamera = action != null && action.equals(MediaStore.ACTION_IMAGE_CAPTURE);
    }
    return isCamera ? getCaptureImageOutputUri() : data.getData();
}

public static void addImageToGallery(final String filePath, final Context context) {

    ContentValues values = new ContentValues();

    values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
    values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
    values.put(MediaStore.MediaColumns.DATA, filePath);

    context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
}

}

dharmeshmp commented 8 years ago
mCropImageView.setOnGetCroppedImageCompleteListener(this);
    mCropImageView.getCroppedImageAsync(mCropImageView.getCropShape(), 0, 0);

remove this two lines at end of oncreate method because this two lines already is there in your onStart method.. apart from it there is no issue in your code. i have tested your code in my project.

also change path

File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
            + "/CropImages");

so you can see imges

mayurxd commented 8 years ago

Now when taking pic form camera it taking too long for cropping

i cannot see any image in gallery and is there any way i can make save button after cropping image which stores image in gallary

dharmeshmp commented 8 years ago

replace your two method and i have added code for publish image in galary..


    static final String TAG = "YOUR-TAG-NAME";

    private void storeImage(Bitmap image) {
        File pictureFile = getOutputMediaFile();
        if (pictureFile == null) {
            Log.d(TAG,
                    "Error creating media file, check storage permissions: ");// e.getMessage());
            return;
        }
        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            image.compress(Bitmap.CompressFormat.PNG, 90, fos);
            fos.close();

        } catch (FileNotFoundException e) {
            Log.d(TAG, "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d(TAG, "Error accessing file: " + e.getMessage());
        }

        ContentValues values = new ContentValues();

        values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
        values.put(MediaStore.MediaColumns.DATA, pictureFile.getPath());

        getApplicationContext().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
    }

    private File getOutputMediaFile() {
        // To be safe, you should check that the SDCard is mounted
        // using Environment.getExternalStorageState() before doing this.
        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
                + "/CropImages");

        // This location works best if you want the created images to be shared
        // between applications and persist after your app has been uninstalled.

        // Create the storage directory if it does not exist
        if (!mediaStorageDir.exists()) {
            if (!mediaStorageDir.mkdirs()) {
                return null;
            }
        }
        // Create a media file name
        String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmm").format(new Date());
        File mediaFile;
        String mImageName = "MI_" + timeStamp + ".jpg";
        mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName);
        return mediaFile;
    }
ArthurHub commented 8 years ago

@mayurxd did it worked for you? what were you missing in the library? do you have a suggestion? maybe a sample documentation that can help?

mayurxd commented 8 years ago

its working fine if want to save already existing image. on other hand if you take image from camera sometimes it do not works and couple of time i faced forced closed while editing and saving image taken by camera.

what i am doing wrong? here is my activity

public class MainActivity extends Activity implements CropImageView.OnSetImageUriCompleteListener, CropImageView.OnGetCroppedImageCompleteListener {

//region: Fields and Consts

private static final int DEFAULT_ASPECT_RATIO_VALUES = 20;

private static final int ROTATE_NINETY_DEGREES = 90;

private static final String ASPECT_RATIO_X = "ASPECT_RATIO_X";

private static final String ASPECT_RATIO_Y = "ASPECT_RATIO_Y";

private static final int ON_TOUCH = 1;

private CropImageView mCropImageView;

private int mAspectRatioX = DEFAULT_ASPECT_RATIO_VALUES;

private int mAspectRatioY = DEFAULT_ASPECT_RATIO_VALUES;

Bitmap croppedImage;

//endregion

// Saves the state upon rotating the screen/restarting the activity
@Override
protected void onSaveInstanceState(@SuppressWarnings("NullableProblems") Bundle bundle) {
    super.onSaveInstanceState(bundle);
    bundle.putInt(ASPECT_RATIO_X, mAspectRatioX);
    bundle.putInt(ASPECT_RATIO_Y, mAspectRatioY);
}

// Restores the state upon rotating the screen/restarting the activity
@Override
protected void onRestoreInstanceState(@SuppressWarnings("NullableProblems") Bundle bundle) {
    super.onRestoreInstanceState(bundle);
    mAspectRatioX = bundle.getInt(ASPECT_RATIO_X);
    mAspectRatioY = bundle.getInt(ASPECT_RATIO_Y);
}

public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    this.requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.activity_main);

    // Initialize components of the app
    mCropImageView = (CropImageView) findViewById(R.id.CropImageView);
    final SeekBar aspectRatioXSeek = (SeekBar) findViewById(R.id.aspectRatioXSeek);
    final SeekBar aspectRatioYSeek = (SeekBar) findViewById(R.id.aspectRatioYSeek);
    Spinner showGuidelinesSpin = (Spinner) findViewById(R.id.showGuidelinesSpin);
    final TextView aspectRatioNum = (TextView) findViewById(R.id.aspectRatioNum);

    if (savedInstanceState == null) {
        mCropImageView.setImageResource(R.drawable.butterfly);
    }

    // Sets sliders to be disabled until fixedAspectRatio is set
    aspectRatioXSeek.setEnabled(false);
    aspectRatioYSeek.setEnabled(false);

    // Set initial spinner value
    showGuidelinesSpin.setSelection(ON_TOUCH);

    //Sets the rotate button
    final Button rotateButton = (Button) findViewById(R.id.Button_rotate);
    rotateButton.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            mCropImageView.rotateImage(ROTATE_NINETY_DEGREES);
        }
    });

    // Sets fixedAspectRatio
    ((ToggleButton) findViewById(R.id.fixedAspectRatioToggle)).setOnCheckedChangeListener(new OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            mCropImageView.setFixedAspectRatio(isChecked);
            if (isChecked) {
                aspectRatioXSeek.setEnabled(true);
                aspectRatioYSeek.setEnabled(true);
            } else {
                aspectRatioXSeek.setEnabled(false);
                aspectRatioYSeek.setEnabled(false);
            }
        }
    });

    // Sets crop shape
    ((ToggleButton) findViewById(R.id.cropShapeToggle)).setOnCheckedChangeListener(new OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            mCropImageView.setCropShape(isChecked ? CropImageView.CropShape.OVAL : CropImageView.CropShape.RECTANGLE);
        }
    });

    // Sets initial aspect ratio to 10/10, for demonstration purposes
    mCropImageView.setAspectRatio(DEFAULT_ASPECT_RATIO_VALUES, DEFAULT_ASPECT_RATIO_VALUES);

    aspectRatioXSeek.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar aspectRatioXSeek, int progress, boolean fromUser) {
            mAspectRatioX = Math.max(1, progress);
            mCropImageView.setAspectRatio(mAspectRatioX, mAspectRatioY);
            aspectRatioNum.setText("(" + mAspectRatioX + ", " + mAspectRatioY + ")");
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
        }
    });

    aspectRatioYSeek.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar aspectRatioYSeek, int progress, boolean fromUser) {
            mAspectRatioY = Math.max(1, progress);
            mCropImageView.setAspectRatio(mAspectRatioX, mAspectRatioY);
            aspectRatioNum.setText("(" + mAspectRatioX + ", " + mAspectRatioY + ")");
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
        }
    });

    // Sets up the Spinner
    showGuidelinesSpin.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
            switch (i) {
                case 0:
                    mCropImageView.setGuidelines(CropImageView.Guidelines.OFF);
                    break;
                case 1:
                    mCropImageView.setGuidelines(CropImageView.Guidelines.ON_TOUCH);
                    break;
                case 2:
                    mCropImageView.setGuidelines(CropImageView.Guidelines.ON);
                    break;
            }
        }

        public void onNothingSelected(AdapterView<?> adapterView) {
            return;
        }
    });

    final TextView snapRadiusNum = (TextView) findViewById(R.id.snapRadiusNum);
    ((SeekBar) findViewById(R.id.snapRadiusSeek)).setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            mCropImageView.setSnapRadius(progress);
            snapRadiusNum.setText(Integer.toString(progress));
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

        }
    });

    findViewById(R.id.Button_crop).setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            mCropImageView.getCroppedImageAsync(mCropImageView.getCropShape(), 0, 0);
        }
    });

    findViewById(R.id.Button_load).setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            startActivityForResult(getPickImageChooserIntent(), 200);
        }
    });

}

static final String TAG = "YOUR-TAG-NAME";

private void storeImage(Bitmap image) {
    File pictureFile = getOutputMediaFile();
    if (pictureFile == null) {
        Log.d(TAG,
                "Error creating media file, check storage permissions: ");// e.getMessage());
        return;
    }
    try {
        FileOutputStream fos = new FileOutputStream(pictureFile);
        image.compress(Bitmap.CompressFormat.PNG, 90, fos);
        fos.close();

    } catch (FileNotFoundException e) {
        Log.d(TAG, "File not found: " + e.getMessage());
    } catch (IOException e) {
        Log.d(TAG, "Error accessing file: " + e.getMessage());
    }

    ContentValues values = new ContentValues();

    values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
    values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
    values.put(MediaStore.MediaColumns.DATA, pictureFile.getPath());

    getApplicationContext().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
}

private File getOutputMediaFile() {
    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this.
    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
            + "/CropImages");

    // This location works best if you want the created images to be shared
    // between applications and persist after your app has been uninstalled.

    // Create the storage directory if it does not exist
    if (!mediaStorageDir.exists()) {
        if (!mediaStorageDir.mkdirs()) {
            return null;
        }
    }
    // Create a media file name
    String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmm").format(new Date());
    File mediaFile;
    String mImageName = "MI_" + timeStamp + ".jpg";
    mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName);
    return mediaFile;
}

@Override
protected void onStart() {
    super.onStart();
    mCropImageView.setOnSetImageUriCompleteListener(this);
    mCropImageView.setOnGetCroppedImageCompleteListener(this);
}

@Override
protected void onStop() {
    super.onStop();
    mCropImageView.setOnSetImageUriCompleteListener(null);
    mCropImageView.setOnGetCroppedImageCompleteListener(null);
}

@Override
public void onSetImageUriComplete(CropImageView view, Uri uri, Exception error) {
    if (error == null) {
        Toast.makeText(mCropImageView.getContext(), "Image load successful", Toast.LENGTH_SHORT).show();
    } else {
        Toast.makeText(mCropImageView.getContext(), "Image load failed: " + error.getMessage(), Toast.LENGTH_LONG).show();
    }
}

@Override
public void onGetCroppedImageComplete(CropImageView view, Bitmap bitmap, Exception error) {
    if (error == null) {
        croppedImage = bitmap;
        ImageView croppedImageView = (ImageView) findViewById(R.id.croppedImageView);
        croppedImageView.setImageBitmap(croppedImage);

        //CapturePhotoUtils cp;
        //cp.insertImage(bitmap,"","");

    } else {
        Toast.makeText(mCropImageView.getContext(), "Image crop failed: " + error.getMessage(), Toast.LENGTH_LONG).show();
    }

    if (error == null) {
        storeImage(bitmap);
    } else {
        //Error
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == Activity.RESULT_OK) {
        Uri imageUri = getPickImageResultUri(data);
        ((CropImageView) findViewById(R.id.CropImageView)).setImageUriAsync(imageUri);

    }
}

/**
 * Create a chooser intent to select the source to get image from.<br/>
 * The source can be camera's (ACTION_IMAGE_CAPTURE) or gallery's (ACTION_GET_CONTENT).<br/>
 * All possible sources are added to the intent chooser.
 */
public Intent getPickImageChooserIntent() {

    // Determine Uri of camera image to save.
    Uri outputFileUri = getCaptureImageOutputUri();

    List<Intent> allIntents = new ArrayList<>();
    PackageManager packageManager = getPackageManager();

    // collect all camera intents
    Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
    for (ResolveInfo res : listCam) {
        Intent intent = new Intent(captureIntent);
        intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
        intent.setPackage(res.activityInfo.packageName);
        if (outputFileUri != null) {
            intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
        }
        allIntents.add(intent);
    }

    // collect all gallery intents
    Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT);
    galleryIntent.setType("image/*");
    List<ResolveInfo> listGallery = packageManager.queryIntentActivities(galleryIntent, 0);
    for (ResolveInfo res : listGallery) {
        Intent intent = new Intent(galleryIntent);
        intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
        intent.setPackage(res.activityInfo.packageName);
        allIntents.add(intent);
    }

    // the main intent is the last in the list (fucking android) so pickup the useless one
    Intent mainIntent = allIntents.get(allIntents.size() - 1);
    for (Intent intent : allIntents) {
        if (intent.getComponent().getClassName().equals("com.android.documentsui.DocumentsActivity")) {
            mainIntent = intent;
            break;
        }
    }
    allIntents.remove(mainIntent);

    // Create a chooser from the main intent
    Intent chooserIntent = Intent.createChooser(mainIntent, "Select source");

    // Add all other intents
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, allIntents.toArray(new Parcelable[allIntents.size()]));

    return chooserIntent;
}

/**
 * Get URI to image received from capture by camera.
 */
private Uri getCaptureImageOutputUri() {
    Uri outputFileUri = null;
    File getImage = getExternalCacheDir();
    if (getImage != null) {
        outputFileUri = Uri.fromFile(new File(getImage.getPath(), "pickImageResult.jpeg"));
    }
    return outputFileUri;
}

/**
 * Get the URI of the selected image from {@link #getPickImageChooserIntent()}.<br/>
 * Will return the correct URI for camera and gallery image.
 *
 * @param data the returned data of the activity result
 */
public Uri getPickImageResultUri(Intent data) {
    boolean isCamera = true;
    if (data != null) {
        String action = data.getAction();
        isCamera = action != null && action.equals(MediaStore.ACTION_IMAGE_CAPTURE);
    }
    return isCamera ? getCaptureImageOutputUri() : data.getData();
}

public static void addImageToGallery(final String filePath, final Context context) {

    ContentValues values = new ContentValues();

    values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
    values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
    values.put(MediaStore.MediaColumns.DATA, filePath);

    context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
}

}

ArthurHub commented 8 years ago

you may have memory issues if you try to handle large bitmaps setImageUriAsync() will use down-sampling to lower the memory usage for the image, but in crop it will return the full sized bitmap when you use don't provide required width/height to getCroppedImageAsync. also in code you re-set the cropped image back to but then it can be very large to handle for rotation that may result in OOM. if you do need to save a large image you may need to handle the cropping manually to save the stream without loading a bitmap into memory.

can you describe what are you trying to do.

mayurxd commented 8 years ago

images taken by the camera are around 2-8mb in size .

what i am doing is i wanted to save edited image so i can further use them in my app and apply zoom on it.

ArthurHub commented 8 years ago

should work fine... make sure you release the bitmaps after cropping as soon as you done saving them to release the memory used by them. can you provides error details for the issues you see?

mayurxd commented 8 years ago

while handling images from camera its skipping frames

02-22 12:43:55.251 8504-8504/com.example.croppersample I/Choreographer: Skipped 771 frames! The application may be doing too much work on its main thread.

and then it crashed

02-22 12:44:19.071 8504-8504/com.example.croppersample I/Timeline: Timeline: Activity_launch_request id:com.android.camera2 time:28821841 02-22 12:44:28.851 8504-8504/com.example.croppersample W/ContextImpl: Failed to ensure directory: /storage/usbdisk0/Android/data/com.example.croppersample/cache 02-22 12:44:28.891 8504-8504/com.example.croppersample I/Adreno-EGL: : EGL 1.4 QUALCOMM build: () OpenGL ES Shader Compiler Version: E031.24.02.07 Build Date: 12/04/14 Thu Local Branch: Remote Branch: Local Patches: Reconstruct Branch: 02-22 12:44:28.961 8504-8504/com.example.croppersample I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@41fa92b8 time:28831731 02-22 12:44:40.021 8504-8509/com.example.croppersample I/dalvikvm: threadid=3: reacting to signal 3 02-22 12:44:40.061 8504-8509/com.example.croppersample I/dalvikvm: Wrote stack traces to '/data/anr/traces.txt' 02-22 12:44:43.411 8504-8504/com.example.croppersample A/libc: Fatal signal 6 (SIGABRT) at 0x00000319 (code=0), thread 8504 (e.croppersample)

ArthurHub commented 8 years ago

from what I can tell it hang in request to launch id:com.android.camera2 activity... what action did you do right before the hang? what device are you using?

mayurxd commented 8 years ago

i clicked on crop button right before it hanged ,and image was taken by camera while its skipping frames if you try to scroll or press an button that will cause the force closed. i am using redmi 2 with cynogenmod

ArthurHub commented 8 years ago

that is very strange... you will have to debug it and find out which code hangs... try running the sample app, first too see if it happens there and second to add logs to spot the problematic code. Sorry that I can't be more helpful.

mayurxd commented 8 years ago

thanks for your all help :) i will try diff things , i will post if something works for me