Skip to content

Commit

Permalink
fix(exif-orientation): added support for exif values 2, 4, 5 and 7 (#409
Browse files Browse the repository at this point in the history
)

* fix(exif-orientation): added support for exif values 2, 4, 5 and 7

* chore: ran gradle ktlintFormat

* docs: updated CHANGELOG.md

* style: apply detekt hints

* style: run ktlinFormat
  • Loading branch information
Mouwrice authored Jul 20, 2022
1 parent 2f867e9 commit 212e7a8
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
27 changes: 22 additions & 5 deletions cropper/src/main/java/com/canhub/cropper/BitmapLoadingWorkerJob.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
)
}
Expand Down Expand Up @@ -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?

Expand All @@ -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
}

Expand Down
34 changes: 22 additions & 12 deletions cropper/src/main/java/com/canhub/cropper/BitmapUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ internal object BitmapUtils {
* If no rotation is required the image will not be rotated.<br></br>
* 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!!)
Expand All @@ -84,27 +84,29 @@ 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)
}

/**
* Rotate the given image by given Exif value.<br></br>
* If no rotation is required the image will not be rotated.<br></br>
* 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)
}

/**
Expand Down Expand Up @@ -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
)
}
6 changes: 5 additions & 1 deletion cropper/src/main/java/com/canhub/cropper/CropImageView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 212e7a8

Please sign in to comment.