/** * Sets a Bitmap and initializes the image rotation according to the EXIT data.<br> * <br> * The EXIF can be retrieved by doing the following: <code> * ExifInterface exif = new ExifInterface(path);</code> * * @param bitmap the original bitmap to set; if null, this * @param exif the EXIF information about this bitmap; may be null */ public void setImageBitmap(Bitmap bitmap, ExifInterface exif) { if (bitmap != null && exif != null) { ImageViewUtil.RotateBitmapResult result = ImageViewUtil.rotateBitmapByExif(bitmap, exif); bitmap = result.bitmap; mDegreesRotated = result.degrees; } setImageBitmap(bitmap); }
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { if (mBitmap != null) { final Rect bitmapRect = ImageViewUtil.getBitmapRect(mBitmap, this, mScaleType); mCropOverlayView.setBitmapRect(bitmapRect); } else { mCropOverlayView.setBitmapRect(EMPTY_RECT); } }
/** * Sets a bitmap loaded from the given Android URI as the content of the CropImageView.<br> * Can be used with URI from gallery or camera source.<br> * Will rotate the image by exif data.<br> * * @param uri the URI to load the image from */ public void setImageUri(Uri uri) { if (uri != null) { DisplayMetrics metrics = getResources().getDisplayMetrics(); double densityAdj = metrics.density > 1 ? 1 / metrics.density : 1; int width = (int) (metrics.widthPixels * densityAdj); int height = (int) (metrics.heightPixels * densityAdj); ImageViewUtil.DecodeBitmapResult decodeResult = ImageViewUtil.decodeSampledBitmap(getContext(), uri, width, height); ImageViewUtil.RotateBitmapResult rotateResult = ImageViewUtil.rotateBitmapByExif(getContext(), decodeResult.bitmap, uri); setImageBitmap(rotateResult.bitmap); mLoadedImageUri = uri; mLoadedSampleSize = decodeResult.sampleSize; mDegreesRotated = rotateResult.degrees; } }
/** * Gets the cropped image based on the current crop window.<br> * If image loaded from URI will use sample size to fir the requested width and height. * * @return a new Bitmap representing the cropped image */ public Bitmap getCroppedImage(int reqWidth, int reqHeight) { if (mBitmap != null) { if (mLoadedImageUri != null && mLoadedSampleSize > 1) { Rect rect = getActualCropRectNoRotation(); reqWidth = reqWidth > 0 ? reqWidth : rect.width(); reqHeight = reqHeight > 0 ? reqHeight : rect.height(); ImageViewUtil.DecodeBitmapResult result = ImageViewUtil.decodeSampledBitmapRegion( getContext(), mLoadedImageUri, rect, reqWidth, reqHeight); Bitmap bitmap = result.bitmap; if (mDegreesRotated > 0) { bitmap = ImageViewUtil.rotateBitmap(bitmap, mDegreesRotated); } return bitmap; } else { Rect rect = getActualCropRect(); return Bitmap.createBitmap(mBitmap, rect.left, rect.top, rect.width(), rect.height()); } } else { return null; } }
/** * Gets the crop window's position relative to the source Bitmap (not the image displayed in the * CropImageView). * * @return a RectF instance containing cropped area boundaries of the source Bitmap */ public Rect getActualCropRect() { if (mBitmap != null) { final Rect displayedImageRect = ImageViewUtil.getBitmapRect(mBitmap, mImageView, mScaleType); // Get the scale factor between the actual Bitmap dimensions and the displayed dimensions for // width. final float actualImageWidth = mBitmap.getWidth(); final float displayedImageWidth = displayedImageRect.width(); final float scaleFactorWidth = actualImageWidth / displayedImageWidth; // Get the scale factor between the actual Bitmap dimensions and the displayed dimensions for // height. final float actualImageHeight = mBitmap.getHeight(); final float displayedImageHeight = displayedImageRect.height(); final float scaleFactorHeight = actualImageHeight / displayedImageHeight; // Get crop window position relative to the displayed image. final float displayedCropLeft = Edge.LEFT.getCoordinate() - displayedImageRect.left; final float displayedCropTop = Edge.TOP.getCoordinate() - displayedImageRect.top; final float displayedCropWidth = Edge.getWidth(); final float displayedCropHeight = Edge.getHeight(); // Scale the crop window position to the actual size of the Bitmap. float actualCropLeft = displayedCropLeft * scaleFactorWidth; float actualCropTop = displayedCropTop * scaleFactorHeight; float actualCropRight = actualCropLeft + displayedCropWidth * scaleFactorWidth; float actualCropBottom = actualCropTop + displayedCropHeight * scaleFactorHeight; // Correct for floating point errors. Crop rect boundaries should not exceed the source Bitmap // bounds. actualCropLeft = Math.max(0f, actualCropLeft); actualCropTop = Math.max(0f, actualCropTop); actualCropRight = Math.min(mBitmap.getWidth(), actualCropRight); actualCropBottom = Math.min(mBitmap.getHeight(), actualCropBottom); return new Rect( (int) actualCropLeft, (int) actualCropTop, (int) actualCropRight, (int) actualCropBottom); } else { return null; } }
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (mBitmap != null) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // Bypasses a baffling bug when used within a ScrollView, where // heightSize is set to 0. if (heightSize == 0) { heightSize = mBitmap.getHeight(); } int desiredWidth; int desiredHeight; double viewToBitmapWidthRatio = Double.POSITIVE_INFINITY; double viewToBitmapHeightRatio = Double.POSITIVE_INFINITY; // Checks if either width or height needs to be fixed if (widthSize < mBitmap.getWidth()) { viewToBitmapWidthRatio = (double) widthSize / (double) mBitmap.getWidth(); } if (heightSize < mBitmap.getHeight()) { viewToBitmapHeightRatio = (double) heightSize / (double) mBitmap.getHeight(); } // If either needs to be fixed, choose smallest ratio and calculate // from there if (viewToBitmapWidthRatio != Double.POSITIVE_INFINITY || viewToBitmapHeightRatio != Double.POSITIVE_INFINITY) { if (viewToBitmapWidthRatio <= viewToBitmapHeightRatio) { desiredWidth = widthSize; desiredHeight = (int) (mBitmap.getHeight() * viewToBitmapWidthRatio); } else { desiredHeight = heightSize; desiredWidth = (int) (mBitmap.getWidth() * viewToBitmapHeightRatio); } } // Otherwise, the picture is within frame layout bounds. Desired // width is // simply picture size else { desiredWidth = mBitmap.getWidth(); desiredHeight = mBitmap.getHeight(); } int width = getOnMeasureSpec(widthMode, widthSize, desiredWidth); int height = getOnMeasureSpec(heightMode, heightSize, desiredHeight); mLayoutWidth = width; mLayoutHeight = height; final Rect bitmapRect = ImageViewUtil.getBitmapRect( mBitmap.getWidth(), mBitmap.getHeight(), mLayoutWidth, mLayoutHeight, mScaleType); mCropOverlayView.setBitmapRect(bitmapRect); // MUST CALL THIS setMeasuredDimension(mLayoutWidth, mLayoutHeight); } else { mCropOverlayView.setBitmapRect(EMPTY_RECT); setMeasuredDimension(widthSize, heightSize); } }