diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5ea73a9d..ecbd2569 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
## [x.x.x] - unreleased
+- CropImageView: Added support for handling all EXIF orientation values. [#408](https://github.com/CanHub/Android-Image-Cropper/issues/408)
- CropImageView: Use customOutputUri instance property as a fallback in startCropWorkerTask. [#401](https://github.com/CanHub/Android-Image-Cropper/issues/401)
- CropImageOptions: Option to change progress bar color. [#390](https://github.com/CanHub/Android-Image-Cropper/issues/390)
- Sample: Showcase 2:1 aspect ratio. [#386](https://github.com/CanHub/Android-Image-Cropper/issues/386)
diff --git a/cropper/src/main/java/com/canhub/cropper/BitmapLoadingWorkerJob.kt b/cropper/src/main/java/com/canhub/cropper/BitmapLoadingWorkerJob.kt
index 7930cfc8..116552ac 100644
--- a/cropper/src/main/java/com/canhub/cropper/BitmapLoadingWorkerJob.kt
+++ b/cropper/src/main/java/com/canhub/cropper/BitmapLoadingWorkerJob.kt
@@ -40,14 +40,16 @@ class BitmapLoadingWorkerJob internal constructor(
val decodeResult =
BitmapUtils.decodeSampledBitmap(context, uri, width, height)
if (isActive) {
- val rotateResult =
- BitmapUtils.rotateBitmapByExif(decodeResult.bitmap, context, uri)
+ val orientateResult =
+ BitmapUtils.orientateBitmapByExif(decodeResult.bitmap, context, uri)
onPostExecute(
Result(
uri = uri,
- bitmap = rotateResult.bitmap,
+ bitmap = orientateResult.bitmap,
loadSampleSize = decodeResult.sampleSize,
- degreesRotated = rotateResult.degrees
+ degreesRotated = orientateResult.degrees,
+ flipHorizontally = orientateResult.flipHorizontally,
+ flipVertically = orientateResult.flipVertically
)
)
}
@@ -102,6 +104,12 @@ class BitmapLoadingWorkerJob internal constructor(
/** The degrees the image was rotated */
val degreesRotated: Int
+ /** If the image was flipped horizontally */
+ var flipHorizontally: Boolean = false
+
+ /** If the image was flipped vertically */
+ var flipVertically: Boolean = false
+
/** The error that occurred during async bitmap loading. */
val error: Exception?
@@ -116,11 +124,20 @@ class BitmapLoadingWorkerJob internal constructor(
fun getUriFilePath(context: Context, uniqueName: Boolean = false): String =
getFilePathFromUri(context, uriContent, uniqueName)
- internal constructor(uri: Uri, bitmap: Bitmap?, loadSampleSize: Int, degreesRotated: Int) {
+ internal constructor(
+ uri: Uri,
+ bitmap: Bitmap?,
+ loadSampleSize: Int,
+ degreesRotated: Int,
+ flipHorizontally: Boolean,
+ flipVertically: Boolean
+ ) {
uriContent = uri
this.bitmap = bitmap
this.loadSampleSize = loadSampleSize
this.degreesRotated = degreesRotated
+ this.flipHorizontally = flipHorizontally
+ this.flipVertically = flipVertically
error = null
}
diff --git a/cropper/src/main/java/com/canhub/cropper/BitmapUtils.kt b/cropper/src/main/java/com/canhub/cropper/BitmapUtils.kt
index bf9f0ee6..707c3db8 100644
--- a/cropper/src/main/java/com/canhub/cropper/BitmapUtils.kt
+++ b/cropper/src/main/java/com/canhub/cropper/BitmapUtils.kt
@@ -74,7 +74,7 @@ internal object BitmapUtils {
* If no rotation is required the image will not be rotated.
* New bitmap is created and the old one is recycled.
*/
- fun rotateBitmapByExif(bitmap: Bitmap?, context: Context, uri: Uri?): RotateBitmapResult {
+ fun orientateBitmapByExif(bitmap: Bitmap?, context: Context, uri: Uri?): RotateBitmapResult {
var ei: ExifInterface? = null
try {
val `is` = context.contentResolver.openInputStream(uri!!)
@@ -84,7 +84,7 @@ internal object BitmapUtils {
}
} catch (ignored: Exception) {
}
- return if (ei != null) rotateBitmapByExif(bitmap, ei) else RotateBitmapResult(bitmap, 0)
+ return if (ei != null) orientateBitmapByExif(bitmap, ei) else RotateBitmapResult(bitmap, 0)
}
/**
@@ -92,19 +92,21 @@ internal object BitmapUtils {
* If no rotation is required the image will not be rotated.
* New bitmap is created and the old one is recycled.
*/
- fun rotateBitmapByExif(bitmap: Bitmap?, exif: ExifInterface): RotateBitmapResult {
- val degrees: Int = when (
- exif.getAttributeInt(
- ExifInterface.TAG_ORIENTATION,
- ExifInterface.ORIENTATION_NORMAL
- )
- ) {
- ExifInterface.ORIENTATION_ROTATE_90 -> 90
+ fun orientateBitmapByExif(bitmap: Bitmap?, exif: ExifInterface): RotateBitmapResult {
+ val orientationAttributeInt =
+ exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
+ val degrees: Int = when (orientationAttributeInt) {
+ ExifInterface.ORIENTATION_ROTATE_90, ExifInterface.ORIENTATION_TRANSVERSE,
+ ExifInterface.ORIENTATION_TRANSPOSE -> 90
ExifInterface.ORIENTATION_ROTATE_180 -> 180
ExifInterface.ORIENTATION_ROTATE_270 -> 270
else -> 0
}
- return RotateBitmapResult(bitmap, degrees)
+ val flipHorizontally = orientationAttributeInt == ExifInterface.ORIENTATION_FLIP_HORIZONTAL ||
+ orientationAttributeInt == ExifInterface.ORIENTATION_TRANSPOSE
+ val flipVertically = orientationAttributeInt == ExifInterface.ORIENTATION_FLIP_VERTICAL ||
+ orientationAttributeInt == ExifInterface.ORIENTATION_TRANSVERSE
+ return RotateBitmapResult(bitmap, degrees, flipHorizontally, flipVertically)
}
/**
@@ -970,6 +972,14 @@ internal object BitmapUtils {
/**
* The degrees the image was rotated
*/
- val degrees: Int
+ val degrees: Int,
+ /**
+ * If the image was flipped horizontally
+ */
+ val flipHorizontally: Boolean = false,
+ /**
+ * If the image was flipped vertically
+ */
+ val flipVertically: Boolean = false
)
}
diff --git a/cropper/src/main/java/com/canhub/cropper/CropImageView.kt b/cropper/src/main/java/com/canhub/cropper/CropImageView.kt
index 4f889513..f8d9ba46 100644
--- a/cropper/src/main/java/com/canhub/cropper/CropImageView.kt
+++ b/cropper/src/main/java/com/canhub/cropper/CropImageView.kt
@@ -711,9 +711,11 @@ class CropImageView @JvmOverloads constructor(context: Context, attrs: Attribute
val setBitmap: Bitmap?
var degreesRotated = 0
if (bitmap != null && exif != null) {
- val result = BitmapUtils.rotateBitmapByExif(bitmap, exif)
+ val result = BitmapUtils.orientateBitmapByExif(bitmap, exif)
setBitmap = result.bitmap
degreesRotated = result.degrees
+ mFlipHorizontally = result.flipHorizontally
+ mFlipVertically = result.flipVertically
mInitialDegreesRotated = result.degrees
} else setBitmap = bitmap
@@ -866,6 +868,8 @@ class CropImageView @JvmOverloads constructor(context: Context, attrs: Attribute
setProgressBarVisibility()
if (result.error == null) {
mInitialDegreesRotated = result.degreesRotated
+ mFlipHorizontally = result.flipHorizontally
+ mFlipVertically = result.flipVertically
setBitmap(
result.bitmap,
0,