Recently I needed to implement avatar image upload from an Android app, I didn't found a library that did all that I needed so I forked a pretty good one and made it better, check it out: Android Image Cropper.
See also the followup post: Android Image Cropper async support and custom progress UI.
See also the followup post: Android Image Cropper async support and custom progress UI.
Requirements:
- Pick image from camera or gallery using single chooser.
- Select circular crop window in the image for the avatar.
- Limit output avatar image to 500×500 pixels.
- Efficient memory usage.
Adjust, crop, or rotate a photo. On your Android device, open the Google Photos app. Open the photo you want to edit. To add or adjust a filter, tap Photo filters. Tap to apply a filter, tap again to adjust. To manually change lighting, color, or add effects, tap Edit. At the top right, tap Save. The famous photo crop app on iPhone is now available on Android market too. Many Unique features that no cropping app in market provides. Rotate the photo.
Obstacles:
- Creating single chooser intent for camera and gallery is not so trivial.
- Android crop activity is limited, unreliable and is internal API.
- Image taken by camera may be rotated.
- Picked image can be large and cause memory issues if loaded in full resolution.
After trying cropper library, I decide to fork it, add circular crop support option inspired by another fork, fix some of the reported bugs and most importantly add support for loading image from Android URI that received from camera or gallery activity result.
- Same code can be used for camera and gallery source.
- Automatically rotate the image by exif data.
- Use sampling and lower density to conserve memory usage.
- When cropped image is requested it will again use sampling of the original image to create bitmap of the required size without loading the full image or lowering the quality of the cropped image.
Check out the Gists or see the code below on how to create image source chooser Intent and use Android Image Cropper library to crop the picked image.
- Create Intent using getPickImageChooserIntent() that will allow to choose camera or gallery sources.
- Use predefined URI from getCaptureImageOutputUri() for camera source.
- Start activity by intent chooser.
- On activity result retrieve the picked image URI by getPickImageResultUri()
- For camera source use the predefined URI from getCaptureImageOutputUri()
- For gallery source use Intent.getData()
- Set the image into CropImageView using setImageUriAsync(Uri uri)
- The image will be loaded using ContentResolver
- The image will be sampled to the size of the device screen with lower density.
- When the user finishes with cropping he/she will click on 'crop' button.
- Retrieve the cropped image using getCroppedImage(500, 500) .
- Will use BitmapRegionDecoder to load only the cropped region
- The image will be sampled to the requested size.
Add write external storage permissions to the manifest as some sources (DropBox, OneDrive, Etc.) use external storage to return the image resulting in “java.io.FileNotFoundException … open failed: EACCES (Permission denied)”.
See it on Gists.