how to set the output image use com.android.camera.action.CROP
This question is all over stackoverflow. And I'm glad it is since I had to sort this out myself recently. I'll do my best to mark some duplicates as I go but I prefer this one since it addresses the issue with the limited image size.
Short Answer
The short answer is not to use the return-data option. Read more about that option and how to retrieve the image then here: http://www.androidworks.com/crop_large_photos_with_android. The article does a great job listing the (known) configuration options for the Intent and how to use them.
Option #2: If you set return-data to "false", you will not receive a Bitmap back from the onActivityResult Intent in-line, instead you will need to set MediaStore.EXTRA_OUTPUT to a Uri (of File scheme only) where you want the Bitmap to be stored. This has some restrictions, first you need to have a temp filesystem location in order to give the file scheme URI, not a huge problem (except on some devices that don't have sdcards).
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
thiz = this;
setContentView(R.layout.main);
mBtn = (Button) findViewById(R.id.btnLaunch);
photo = (ImageView) findViewById(R.id.imgPhoto);
mBtn.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
try {
// Launch picker to choose photo for selected contact
Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
intent.setType("image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", aspectX);
intent.putExtra("aspectY", aspectY);
intent.putExtra("outputX", outputX);
intent.putExtra("outputY", outputY);
intent.putExtra("scale", scale);
intent.putExtra("return-data", return_data);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getTempUri());
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection",!faceDetection); // lol, negative boolean noFaceDetection
if (circleCrop) {
intent.putExtra("circleCrop", true);
}
startActivityForResult(intent, PHOTO_PICKED);
} catch (ActivityNotFoundException e) {
Toast.makeText(thiz, R.string.photoPickerNotFoundText, Toast.LENGTH_LONG).show();
}
}
});
}
private Uri getTempUri() {
return Uri.fromFile(getTempFile());
}
private File getTempFile() {
if (isSDCARDMounted()) {
File f = new File(Environment.getExternalStorageDirectory(),TEMP_PHOTO_FILE);
try {
f.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
Toast.makeText(thiz, R.string.fileIOIssue, Toast.LENGTH_LONG).show();
}
return f;
} else {
return null;
}
}
private boolean isSDCARDMounted(){
String status = Environment.getExternalStorageState();
if (status.equals(Environment.MEDIA_MOUNTED))
return true;
return false;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case PHOTO_PICKED:
if (resultCode == RESULT_OK) {
if (data == null) {
Log.w(TAG, "Null data, but RESULT_OK, from image picker!");
Toast.makeText(this, R.string.no_photo_picked,
Toast.LENGTH_SHORT).show();
return;
}
final Bundle extras = data.getExtras();
if (extras != null) {
File tempFile = getTempFile();
// new logic to get the photo from a URI
if (data.getAction() != null) {
processPhotoUpdate(tempFile);
}
}
}
break;
}
}
Code example from: http://www.androidworks.com/crop_large_photos_with_android
More Information
The long answer is not to use that intent at all. Continue reading to find out why.
Unofficial API
The core of the problem is the unofficial intent. Unofficial as in not part of the public API. Currently it works for most devices but most just isn't enough. Also Google can change this intent anytime without letting you know. Breaking along all the apps using it. Much like how the calendar API was once unofficial. In fact this crop intent has already changed once. So avoid using this intent. There are alternatives. Feel free to ignore this advice.
Just to proof the "works for some devices statement" follow this link and enjoy frustrated Android developers discussing what should be considered part of the core android features (and isn't): https://code.google.com/p/android/issues/detail?id=1480
Time for example code? Check this github project: https://github.com/lorensiuswlt/AndroidImageCrop
About Size Limit
Another issue I experienced while exploring this intent is the image crop size limit. This can easily be reproduced using the above example code and an image size of anything above 300 pixels. Basically what this original question is all about. In the best case your app will crash. But I've seen worse up to hanging devices that could only be reset by removing the battery.
Now if you remove that 'return-data' option you'll be able to run it again. More information on how to get to the result is found in the short answer where I referenced this link already: http://www.androidworks.com/crop_large_photos_with_android
The Solution
So a lot of problems. Problems require a solution. The only decent solution until Google comes up with a public API for this is to provide your own crop intent. Just get your hands on a proper crop library like this one on github: https://github.com/lvillani/android-cropimage
The project lacks some documentation but since it's an extract of the unofficial android crop intent you can use the examples listed on top to get started. Just make sure not to use the return-data option. Ah and check out the CropImageIntentBuilder class. That should let you easily create an intent for the cropping. Don't forget to add this Activity to your manifest and the permissions to write to external data storage.
private void doCrop(File croppedResult){
CropImageIntentBuilder builder = new CropImageIntentBuilder(600,600, croppedResult);
// don't forget this, the error handling within the library is just ignoring if you do
builder.setSourceImage(mImageCaptureUri);
Intent intent = builder.getIntent(getApplicationContext());
// do not use return data for big images
intent.putExtra("return-data", false);
// start an activity and then get the result back in onActivtyResult
startActivityForResult(intent, CROP_FROM_CAMERA);
}
Using this library also opens the doors to more customisation. Good to know is the core bitmap functionally used for resizing: How to crop the parsed image in android?
And that's it. Enjoy!
That Intent is not part of the public Android API and is not guaranteed to work on all devices. It was used in earlier versions of android 1.x and 2.x but it's not used anymore and is not recommended. That is probably why it's crashing all over the palce or working improperly.
Use methods such as Bitmap.createBitmap(..)
or Bitmap.createScaledBitmap(..)
to create a resized or cropped version of your original image. These are part of the Android API and are guaranteed to work.
See official docs here and here
To crop a bitmap, you can use Bitmap.createBitmap(Bitmap, int x, int y, int width, int height)
. For example, if you need to crop 10 pixels from each side of a bitmap then use this:
Bitmap croppedBitmap = Bitmap.createBitmap(originalBitmap, 10, 10, originalBitmap.getWidth() - 20, originalBitmap.getHeight() - 20);
If you need to show the selector to the user. Then you can do something like this:
private static final String TEMP_PHOTO_FILE = "temporary_holder.jpg";
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
photoPickerIntent.setType("image/*");
photoPickerIntent.putExtra("crop", "true");
photoPickerIntent.putExtra(MediaStore.EXTRA_OUTPUT, getTempUri());
photoPickerIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
startActivityForResult(photoPickerIntent, REQ_CODE_PICK_IMAGE);
private Uri getTempUri() {
return Uri.fromFile(getTempFile());
}
private File getTempFile() {
if (isSDCARDMounted()) {
File f = new File(Environment.getExternalStorageDirectory(),TEMP_PHOTO_FILE);
try {
f.createNewFile();
} catch (IOException e) {
}
return f;
} else {
return null;
}
}
private boolean isSDCARDMounted(){
String status = Environment.getExternalStorageState();
if (status.equals(Environment.MEDIA_MOUNTED))
return true;
return false;
}
protected void onActivityResult(int requestCode, int resultCode,
Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
switch (requestCode) {
case REQ_CODE_PICK_IMAGE:
if (resultCode == RESULT_OK) {
if (imageReturnedIntent!=null){
File tempFile = getTempFile();
String filePath= Environment.getExternalStorageDirectory()
+ "/temporary_holder.jpg";
System.out.println("path "+filePath);
Bitmap selectedImage = BitmapFactory.decodeFile(filePath);
_image = (ImageView) findViewById(R.id.image);
_image.setImageBitmap(selectedImage );
}
}
}
code from here