Skip to content

Commit

Permalink
handle get cropped image with sampling
Browse files Browse the repository at this point in the history
  • Loading branch information
Arthur Teplitzki committed Feb 12, 2015
1 parent 845c617 commit f7ad6ac
Show file tree
Hide file tree
Showing 4 changed files with 228 additions and 114 deletions.
2 changes: 1 addition & 1 deletion cropper/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ android {
compileSdkVersion 21
buildToolsVersion '21.1.2'
defaultConfig {
minSdkVersion 8
minSdkVersion 10
targetSdkVersion 21
versionCode 1
versionName '1.0'
Expand Down
267 changes: 164 additions & 103 deletions cropper/src/main/java/com/theartofdev/edmodo/cropper/CropImageView.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Bundle;
Expand Down Expand Up @@ -99,6 +100,16 @@ public class CropImageView extends FrameLayout {
* The shape of the cropping area - rectangle/circular.
*/
private CropImageView.CropShape mCropShape;

/**
* The URI that the image was loaded from (if loaded from URI)
*/
private Uri mLoadedImageUri;

/**
* The sample size the image was loaded by if was loaded by URI
*/
private int mLoadedSampleSize = 1;
//endregion

public CropImageView(Context context) {
Expand Down Expand Up @@ -127,6 +138,75 @@ public CropImageView(Context context, AttributeSet attrs) {
init(context);
}

/**
* Set the scale type of the image in the crop view
*/
public ImageView.ScaleType getScaleType() {
return mScaleType;
}

/**
* Set the scale type of the image in the crop view
*/
public void setScaleType(ImageView.ScaleType scaleType) {
mScaleType = scaleType;
if (mImageView != null)
mImageView.setScaleType(mScaleType);
}

/**
* The shape of the cropping area - rectangle/circular.
*/
public CropImageView.CropShape getCropShape() {
return mCropShape;
}

/**
* The shape of the cropping area - rectangle/circular.
*/
public void setCropShape(CropImageView.CropShape cropShape) {
if (cropShape != mCropShape) {
mCropShape = cropShape;
mCropOverlayView.setCropShape(cropShape);
}
}

/**
* Sets whether the aspect ratio is fixed or not; true fixes the aspect ratio, while
* false allows it to be changed.
*
* @param fixAspectRatio Boolean that signals whether the aspect ratio should be
* maintained.
*/
public void setFixedAspectRatio(boolean fixAspectRatio) {
mCropOverlayView.setFixedAspectRatio(fixAspectRatio);
}

/**
* Sets the guidelines for the CropOverlayView to be either on, off, or to show when
* resizing the application.
*
* @param guidelines Integer that signals whether the guidelines should be on, off, or
* only showing when resizing.
*/
public void setGuidelines(int guidelines) {
mCropOverlayView.setGuidelines(guidelines);
}

/**
* Sets the both the X and Y values of the aspectRatio.
*
* @param aspectRatioX int that specifies the new X value of the aspect ratio
* @param aspectRatioY int that specifies the new Y value of the aspect ratio
*/
public void setAspectRatio(int aspectRatioX, int aspectRatioY) {
mAspectRatioX = aspectRatioX;
mCropOverlayView.setAspectRatioX(mAspectRatioX);

mAspectRatioY = aspectRatioY;
mCropOverlayView.setAspectRatioY(mAspectRatioY);
}

/**
* Returns the integer of the imageResource
*/
Expand Down Expand Up @@ -158,8 +238,13 @@ public void setImageBitmap(Bitmap bitmap) {
*/
public void setImageBitmap(Bitmap bitmap, ExifInterface exif) {
if (bitmap != null && exif != null) {
bitmap = ImageViewUtil.rotateBitmapByExif(bitmap, exif);
ImageViewUtil.RotateBitmapResult result = ImageViewUtil.rotateBitmapByExif(bitmap, exif);
bitmap = result.bitmap;
mDegreesRotated = result.degrees;
}
mImageResource = 0;
mLoadedImageUri = null;
mLoadedSampleSize = 1;
setImageBitmap(bitmap);
}

Expand All @@ -172,6 +257,8 @@ public void setImageResource(int resId) {
if (resId != 0) {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId);
setImageBitmap(bitmap);

mImageResource = resId;
}
}

Expand All @@ -190,50 +277,18 @@ public void setImageUri(Uri uri) {

int width = (int) (metrics.widthPixels * densityAdj);
int height = (int) (metrics.heightPixels * densityAdj);
ImageViewUtil.DecodeBitmapResult result = ImageViewUtil.decodeSampledBitmap(getContext(), uri, width, height);

Bitmap rotatedBitmap = ImageViewUtil.rotateBitmapByExif(getContext(), result.bitmap, uri);

setImageBitmap(rotatedBitmap);
}
}

/**
* Gets the cropped image based on the current crop window.
*
* @return a new Bitmap representing the cropped image
*/
public Bitmap getCroppedImage() {
// Crop the subset from the original Bitmap.
Rect rect = getActualCropRect();
return Bitmap.createBitmap(mBitmap, rect.left, rect.top, rect.width(), rect.height());
}

/**
* Gets the cropped circle image based on the current crop selection.
*
* @return a new Circular Bitmap representing the cropped image
*/
public Bitmap getCroppedCircleImage() {

Rect rect = getActualCropRect();

Bitmap output = Bitmap.createBitmap(rect.width(), rect.height(), Bitmap.Config.ARGB_8888);

Canvas canvas = new Canvas(output);

final int color = 0xff424242;
final Paint paint = new Paint();
ImageViewUtil.DecodeBitmapResult decodeResult =
ImageViewUtil.decodeSampledBitmap(getContext(), uri, width, height);

paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
ImageViewUtil.RotateBitmapResult rotateResult =
ImageViewUtil.rotateBitmapByExif(getContext(), decodeResult.bitmap, uri);

canvas.drawCircle(rect.width() / 2, rect.height() / 2, Math.max(rect.width(), rect.height()) / 2, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(mBitmap, rect, rect, paint);
setImageBitmap(rotateResult.bitmap);

return output;
mLoadedImageUri = uri;
mLoadedSampleSize = decodeResult.sampleSize;
mDegreesRotated = rotateResult.degrees;
}
}

/**
Expand Down Expand Up @@ -278,89 +333,94 @@ public Rect getActualCropRect() {
}

/**
* Set the scale type of the image in the crop view
* Gets the crop window's position relative to the source Bitmap (not the image
* displayed in the CropImageView) and the original rotation.
*
* @return a RectF instance containing cropped area boundaries of the source Bitmap
*/
public ImageView.ScaleType getScaleType() {
return mScaleType;
@SuppressWarnings("SuspiciousNameCombination")
public Rect getActualCropRectNoRotation() {
Rect rect = getActualCropRect();
int rotateSide = mDegreesRotated / 90;
if (rotateSide == 1) {
rect.set(rect.top, mBitmap.getWidth() - rect.right, rect.bottom, mBitmap.getWidth() - rect.left);
} else if (rotateSide == 2) {
rect.set(mBitmap.getWidth() - rect.right, mBitmap.getHeight() - rect.bottom, mBitmap.getWidth() - rect.left, mBitmap.getHeight() - rect.top);
} else if (rotateSide == 3) {
rect.set(mBitmap.getHeight() - rect.bottom, rect.left, mBitmap.getHeight() - rect.top, rect.right);
}
rect.set(rect.left * mLoadedSampleSize, rect.top * mLoadedSampleSize, rect.right * mLoadedSampleSize, rect.bottom * mLoadedSampleSize);
return rect;
}

/**
* Set the scale type of the image in the crop view
* Rotates image by the specified number of degrees clockwise. Cycles from 0 to 360
* degrees.
*
* @param degrees Integer specifying the number of degrees to rotate.
*/
public void setScaleType(ImageView.ScaleType scaleType) {
mScaleType = scaleType;
if (mImageView != null)
mImageView.setScaleType(mScaleType);
}
public void rotateImage(int degrees) {

/**
* The shape of the cropping area - rectangle/circular.
*/
public CropImageView.CropShape getCropShape() {
return mCropShape;
}
Matrix matrix = new Matrix();
matrix.postRotate(degrees);
mBitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), matrix, true);
setImageBitmap(mBitmap);

/**
* The shape of the cropping area - rectangle/circular.
*/
public void setCropShape(CropImageView.CropShape cropShape) {
if (cropShape != mCropShape) {
mCropShape = cropShape;
mCropOverlayView.setCropShape(cropShape);
}
mDegreesRotated += degrees;
mDegreesRotated = mDegreesRotated % 360;
}

/**
* Sets whether the aspect ratio is fixed or not; true fixes the aspect ratio, while
* false allows it to be changed.
* Gets the cropped image based on the current crop window.
*
* @param fixAspectRatio Boolean that signals whether the aspect ratio should be
* maintained.
* @return a new Bitmap representing the cropped image
*/
public void setFixedAspectRatio(boolean fixAspectRatio) {
mCropOverlayView.setFixedAspectRatio(fixAspectRatio);
}
public Bitmap getCroppedImage() {
if (mLoadedImageUri != null && mLoadedSampleSize > 1) {
Rect rect = getActualCropRectNoRotation();
ImageViewUtil.DecodeBitmapResult result =
ImageViewUtil.decodeSampledBitmapRegion(getContext(), mLoadedImageUri, rect, rect.width(), rect.height());

Bitmap bitmap = result.bitmap;
if (mDegreesRotated > 0) {
bitmap = ImageViewUtil.rotateBitmap(bitmap, mDegreesRotated);
}

/**
* Sets the guidelines for the CropOverlayView to be either on, off, or to show when
* resizing the application.
*
* @param guidelines Integer that signals whether the guidelines should be on, off, or
* only showing when resizing.
*/
public void setGuidelines(int guidelines) {
mCropOverlayView.setGuidelines(guidelines);
return bitmap;
} else {
Rect rect = getActualCropRect();
return Bitmap.createBitmap(mBitmap, rect.left, rect.top, rect.width(), rect.height());
}
}

/**
* Sets the both the X and Y values of the aspectRatio.
* Gets the cropped circle image based on the current crop selection.
*
* @param aspectRatioX int that specifies the new X value of the aspect ratio
* @param aspectRatioY int that specifies the new Y value of the aspect ratio
* @return a new Circular Bitmap representing the cropped image
*/
public void setAspectRatio(int aspectRatioX, int aspectRatioY) {
mAspectRatioX = aspectRatioX;
mCropOverlayView.setAspectRatioX(mAspectRatioX);
public Bitmap getCroppedOvalImage() {

mAspectRatioY = aspectRatioY;
mCropOverlayView.setAspectRatioY(mAspectRatioY);
}
Bitmap cropped = getCroppedImage();

/**
* Rotates image by the specified number of degrees clockwise. Cycles from 0 to 360
* degrees.
*
* @param degrees Integer specifying the number of degrees to rotate.
*/
public void rotateImage(int degrees) {
int width = cropped.getWidth();
int height = cropped.getHeight();
Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

Matrix matrix = new Matrix();
matrix.postRotate(degrees);
mBitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), matrix, true);
setImageBitmap(mBitmap);
Canvas canvas = new Canvas(output);

mDegreesRotated += degrees;
mDegreesRotated = mDegreesRotated % 360;
final int color = 0xff424242;
final Paint paint = new Paint();

paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);

RectF rect = new RectF(0, 0, width, height);
canvas.drawOval(rect, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(cropped, 0, 0, paint);

return output;
}

//region: Private methods
Expand Down Expand Up @@ -507,6 +567,7 @@ private void init(Context context) {
mImageView.setScaleType(mScaleType);

setImageResource(mImageResource);

mCropOverlayView = (CropOverlayView) v.findViewById(R.id.CropOverlayView);
mCropOverlayView.setInitialAttributeValues(mGuidelines, mFixAspectRatio, mAspectRatioX, mAspectRatioY);
mCropOverlayView.setCropShape(mCropShape);
Expand Down
Loading

0 comments on commit f7ad6ac

Please sign in to comment.