From 25bd77bd1224c064c0a83fc7fba6fe5594b4391f Mon Sep 17 00:00:00 2001 From: Guillaume Date: Wed, 1 Nov 2017 04:52:29 +0100 Subject: [PATCH 1/4] Lossless rotation Possible issue: even though most EXIF tags keep their original value, some of them are changed by android.media.ExifInterface. it.sephiroth.android.library.exif2.ExifInterface did the same, but to different values and/or with different results. --- .../gallery/activities/ViewPagerActivity.kt | 56 ++++++++++++++++--- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt index ae02f2a66..7ed831383 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt @@ -45,7 +45,9 @@ import com.simplemobiletools.gallery.helpers.* import com.simplemobiletools.gallery.models.Medium import kotlinx.android.synthetic.main.activity_medium.* import java.io.File -import java.io.OutputStream +import java.io.FileInputStream +import java.io.FileOutputStream +import java.io.FileNotFoundException import java.util.* class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, ViewPagerFragment.FragmentListener { @@ -463,7 +465,12 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View return@getFileOutputStream } - saveFile(tmpFile, bitmap, it) + if (currPath.isImageFast() && !currPath.isPng()) { // Is always JPEG? + saveRotation(currPath, tmpFile) + } else { + saveFile(tmpFile, bitmap, it as FileOutputStream) + } + if (needsStupidWritePermissions(selectedFile.absolutePath)) { deleteFile(selectedFile) {} } @@ -471,6 +478,12 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View renameFile(tmpFile, selectedFile) { deleteFile(tmpFile) {} } + + it.flush() + it.close() + toast(R.string.file_saved) + mRotationDegrees = 0f + invalidateOptionsMenu() } } catch (e: OutOfMemoryError) { toast(R.string.out_of_memory_error) @@ -483,18 +496,45 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } } - private fun saveFile(file: File, bitmap: Bitmap, out: OutputStream) { + private fun saveFile(file: File, bitmap: Bitmap, out: FileOutputStream) { val matrix = Matrix() matrix.postRotate(mRotationDegrees) val bmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true) bmp.compress(file.getCompressionFormat(), 90, out) - out.flush() - out.close() - toast(R.string.file_saved) - mRotationDegrees = 0f - invalidateOptionsMenu() } + private fun saveRotation(input: String, out: File) { + var inputStream: FileInputStream? = null + var outputStream: FileOutputStream? = null + try { + inputStream = FileInputStream(input) + outputStream = FileOutputStream(out) + inputStream.copyTo(outputStream) + } catch (ignored: FileNotFoundException) { + } finally { + inputStream?.close() + outputStream?.close() + } + if (mRotationDegrees != 0f) { + val exif = ExifInterface(out.absolutePath) + var orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL) + var orientationDegrees = when (orientation) { + 8 -> 270f + 3 -> 180f + 6 -> 90f + else -> 0f + } + orientationDegrees = (orientationDegrees + mRotationDegrees) % 360 + orientation = when (orientationDegrees) { + 90f -> 6 + 180f -> 3 + 270f -> 8 + else -> 1 + } + exif.setAttribute(ExifInterface.TAG_ORIENTATION, ""+ orientation) + exif.saveAttributes() + } + } private fun isShowHiddenFlagNeeded(): Boolean { val file = File(mPath) if (file.isHidden) From fdc10638389b77db88e29ec622eb283b246e3b4d Mon Sep 17 00:00:00 2001 From: Guillaume Date: Wed, 1 Nov 2017 14:51:11 +0100 Subject: [PATCH 2/4] Update ViewPagerActivity.kt - Removed `mRotationDegrees != 0f` check, because save buttton wouldn't have shown anyway - Check if output file is written - Added helpers functions (with `.toString()` instead of using `""+`) --- .../gallery/activities/ViewPagerActivity.kt | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt index 7ed831383..59d01ae61 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt @@ -515,26 +515,29 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View inputStream?.close() outputStream?.close() } - if (mRotationDegrees != 0f) { + if (out.exists()) { val exif = ExifInterface(out.absolutePath) var orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL) - var orientationDegrees = when (orientation) { - 8 -> 270f - 3 -> 180f - 6 -> 90f - else -> 0f - } - orientationDegrees = (orientationDegrees + mRotationDegrees) % 360 - orientation = when (orientationDegrees) { - 90f -> 6 - 180f -> 3 - 270f -> 8 - else -> 1 - } - exif.setAttribute(ExifInterface.TAG_ORIENTATION, ""+ orientation) + var orientationDegrees = (degreesForRotation(orientation) + mRotationDegrees) % 360 + exif.setAttribute(ExifInterface.TAG_ORIENTATION, rotationFromDegrees(orientationDegrees)) exif.saveAttributes() } } + + private fun degreesForRotation(orientation: Int) = when (orientation) { + ExifInterface.ORIENTATION_ROTATE_270 -> 270f + ExifInterface.ORIENTATION_ROTATE_180 -> 180f + ExifInterface.ORIENTATION_ROTATE_90 -> 90f + else -> 0f + } + + private fun rotationFromDegrees(degrees: Float) = when (degrees) { + 90f -> ExifInterface.ORIENTATION_ROTATE_90 + 180f -> ExifInterface.ORIENTATION_ROTATE_180 + 270f -> ExifInterface.ORIENTATION_ROTATE_270 + else -> ExifInterface.ORIENTATION_NORMAL + }.toString() + private fun isShowHiddenFlagNeeded(): Boolean { val file = File(mPath) if (file.isHidden) From 76a9dfe6c72d379fea26a9d010c91f60ade9613d Mon Sep 17 00:00:00 2001 From: Guillaume Date: Wed, 1 Nov 2017 14:52:49 +0100 Subject: [PATCH 3/4] .isJpg() --- .../simplemobiletools/gallery/activities/ViewPagerActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt index 59d01ae61..0646498f3 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt @@ -465,7 +465,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View return@getFileOutputStream } - if (currPath.isImageFast() && !currPath.isPng()) { // Is always JPEG? + if (currPath.isJpg()) { saveRotation(currPath, tmpFile) } else { saveFile(tmpFile, bitmap, it as FileOutputStream) From 1cecff008c73a4b83d1565bc40ac52736ecbad8f Mon Sep 17 00:00:00 2001 From: Guillaume Date: Wed, 1 Nov 2017 16:12:27 +0100 Subject: [PATCH 4/4] OCD :-P --- .../simplemobiletools/gallery/activities/ViewPagerActivity.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt index 0646498f3..bc325f210 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt @@ -532,9 +532,9 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } private fun rotationFromDegrees(degrees: Float) = when (degrees) { - 90f -> ExifInterface.ORIENTATION_ROTATE_90 - 180f -> ExifInterface.ORIENTATION_ROTATE_180 270f -> ExifInterface.ORIENTATION_ROTATE_270 + 180f -> ExifInterface.ORIENTATION_ROTATE_180 + 90f -> ExifInterface.ORIENTATION_ROTATE_90 else -> ExifInterface.ORIENTATION_NORMAL }.toString()