From 63d39b589a6479dbd81a1d6c040686503a29f2dc Mon Sep 17 00:00:00 2001 From: Guillaume Date: Fri, 3 Nov 2017 17:01:13 +0100 Subject: [PATCH 1/3] Working EXIF lossless on Internal & SD Tested and works on both Internal Storage and External SD cards --- .../gallery/activities/ViewPagerActivity.kt | 116 ++++++++---------- 1 file changed, 52 insertions(+), 64 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 177f0b38d..264fec318 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt @@ -46,8 +46,9 @@ import com.simplemobiletools.gallery.models.Medium import kotlinx.android.synthetic.main.activity_medium.* import java.io.File import java.io.FileInputStream -import java.io.FileNotFoundException import java.io.FileOutputStream +import java.io.InputStream +import java.io.OutputStream import java.util.* class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, ViewPagerFragment.FragmentListener { @@ -454,52 +455,60 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View SaveAsDialog(this, currPath, false) { Thread({ toast(R.string.saving) - if (it.isJpg() && !isPathOnSD(it)) { - if (it == currPath) { - rotateFileByExif(it) - runOnUiThread { - (getCurrentFragment() as? PhotoFragment)?.refreshBitmap() + val selectedFile = File(it) + val tmpFile = File(filesDir, ".tmp_${it.getFilenameFromPath()}") + try { + val bitmap = BitmapFactory.decodeFile(currPath) + getFileOutputStream(tmpFile) { + if (it == null) { + toast(R.string.unknown_error_occurred) + deleteFile(tmpFile) {} + return@getFileOutputStream } - } else { - copyFile(currPath, it) - rotateFileByExif(it) + + if (currPath.isJpg()) { + saveRotation(getCurrentFile(), tmpFile) + } else { + saveFile(tmpFile, bitmap, it as FileOutputStream) + } + + if (tmpFile.length() > 0 && selectedFile.exists()) { + deleteFile(selectedFile) {} + } + copyFile(tmpFile, selectedFile) + scanPath(selectedFile.absolutePath) {} + deleteFile(tmpFile) {} // Not necessary? + toast(R.string.file_saved) + + it.flush() + it.close() + mRotationDegrees = 0f + invalidateOptionsMenu() } - } else { - rotateFileByDegrees(currPath, it) + } catch (e: OutOfMemoryError) { + toast(R.string.out_of_memory_error) + deleteFile(tmpFile) {} + } catch (e: Exception) { + showErrorToast(e) + deleteFile(tmpFile) {} } }).start() } } - private fun rotateFileByDegrees(sourcePath: String, destinationPath: String) { - val tmpFile = File(File(destinationPath).parent, ".tmp_${destinationPath.getFilenameFromPath()}") + private fun copyFile(source: File, destination: File) { + var inputStream: InputStream? = null + var out: OutputStream? = null try { - getFileOutputStream(tmpFile) { - if (it == null) { - toast(R.string.unknown_error_occurred) - return@getFileOutputStream - } - - val bitmap = BitmapFactory.decodeFile(sourcePath) - saveFile(tmpFile, bitmap, it as FileOutputStream) - it.flush() - it.close() - - val destination = File(destinationPath) - deleteFile(destination) { - renameFile(tmpFile, destination) {} - } - - toast(R.string.file_saved) - mRotationDegrees = 0f - invalidateOptionsMenu() + if (needsStupidWritePermissions(destination.absolutePath)) { + getFileDocument(destination.parent) } - } catch (e: OutOfMemoryError) { - toast(R.string.out_of_memory_error) - deleteFile(tmpFile) {} - } catch (e: Exception) { - showErrorToast(e) - deleteFile(tmpFile) {} + out = getFileOutputStreamSync(destination.absolutePath, source.getMimeType(), getFileDocument(destination.parent)) + inputStream = FileInputStream(source) + inputStream.copyTo(out!!) + } finally { + inputStream?.close() + out?.close() } } @@ -510,34 +519,13 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View bmp.compress(file.getCompressionFormat(), 90, out) } - private fun copyFile(sourcePath: String, destinationPath: String) { - var inputStream: FileInputStream? = null - var outputStream: FileOutputStream? = null - try { - inputStream = FileInputStream(sourcePath) - outputStream = FileOutputStream(destinationPath) - inputStream.copyTo(outputStream) - scanPath(destinationPath) {} - } catch (ignored: FileNotFoundException) { - } finally { - inputStream?.close() - outputStream?.close() - } - } - - private fun rotateFileByExif(path: String) { - val exif = ExifInterface(path) - val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL) - val orientationDegrees = (degreesForRotation(orientation) + mRotationDegrees) % 360 + private fun saveRotation(input: File, output: File) { + copyFile(input, output) + val exif = ExifInterface(output.absolutePath) + var orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL) + var orientationDegrees = (degreesForRotation(orientation) + mRotationDegrees) % 360 exif.setAttribute(ExifInterface.TAG_ORIENTATION, rotationFromDegrees(orientationDegrees)) exif.saveAttributes() - if (!config.keepLastModified) { - File(getCurrentPath()).setLastModified(System.currentTimeMillis()) - } - - mRotationDegrees = 0f - invalidateOptionsMenu() - toast(R.string.file_saved) } private fun degreesForRotation(orientation: Int) = when (orientation) { From 598eeb154d11583d1f1be78afa6035994f8b1d9d Mon Sep 17 00:00:00 2001 From: Guillaume Date: Fri, 3 Nov 2017 21:57:56 +0100 Subject: [PATCH 2/3] Improvements as suggested --- .../gallery/activities/ViewPagerActivity.kt | 10 +++------- 1 file changed, 3 insertions(+), 7 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 264fec318..790a082bc 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt @@ -477,7 +477,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } copyFile(tmpFile, selectedFile) scanPath(selectedFile.absolutePath) {} - deleteFile(tmpFile) {} // Not necessary? toast(R.string.file_saved) it.flush() @@ -487,9 +486,9 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } } catch (e: OutOfMemoryError) { toast(R.string.out_of_memory_error) - deleteFile(tmpFile) {} } catch (e: Exception) { showErrorToast(e) + } finally { deleteFile(tmpFile) {} } }).start() @@ -500,9 +499,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View var inputStream: InputStream? = null var out: OutputStream? = null try { - if (needsStupidWritePermissions(destination.absolutePath)) { - getFileDocument(destination.parent) - } out = getFileOutputStreamSync(destination.absolutePath, source.getMimeType(), getFileDocument(destination.parent)) inputStream = FileInputStream(source) inputStream.copyTo(out!!) @@ -522,8 +518,8 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View private fun saveRotation(input: File, output: File) { copyFile(input, output) val exif = ExifInterface(output.absolutePath) - var orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL) - var orientationDegrees = (degreesForRotation(orientation) + mRotationDegrees) % 360 + val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL) + val orientationDegrees = (degreesForRotation(orientation) + mRotationDegrees) % 360 exif.setAttribute(ExifInterface.TAG_ORIENTATION, rotationFromDegrees(orientationDegrees)) exif.saveAttributes() } From 4844e2c2d807423decf4eeaa9b9dcb329745b0b7 Mon Sep 17 00:00:00 2001 From: Guillaume Date: Fri, 3 Nov 2017 22:00:28 +0100 Subject: [PATCH 3/3] One more deleteFile to remove ...now I understand `return@getFileOutputStream`. --- .../simplemobiletools/gallery/activities/ViewPagerActivity.kt | 1 - 1 file changed, 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 790a082bc..c47e1f407 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/activities/ViewPagerActivity.kt @@ -462,7 +462,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View getFileOutputStream(tmpFile) { if (it == null) { toast(R.string.unknown_error_occurred) - deleteFile(tmpFile) {} return@getFileOutputStream }