mirror of
https://github.com/FossifyOrg/Gallery.git
synced 2024-11-30 00:17:58 +01:00
modify exif metadata at rotating image from fullscreen mode + autosave it
This commit is contained in:
parent
0ed110210b
commit
3c37407315
4 changed files with 41 additions and 138 deletions
|
@ -5,10 +5,7 @@ import android.content.Intent
|
||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.graphics.BitmapFactory
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.Matrix
|
|
||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.ColorDrawable
|
||||||
import android.hardware.SensorManager
|
import android.hardware.SensorManager
|
||||||
import android.media.ExifInterface
|
import android.media.ExifInterface
|
||||||
|
@ -27,7 +24,6 @@ import com.simplemobiletools.gallery.R
|
||||||
import com.simplemobiletools.gallery.activities.MediaActivity.Companion.mMedia
|
import com.simplemobiletools.gallery.activities.MediaActivity.Companion.mMedia
|
||||||
import com.simplemobiletools.gallery.adapters.MyPagerAdapter
|
import com.simplemobiletools.gallery.adapters.MyPagerAdapter
|
||||||
import com.simplemobiletools.gallery.asynctasks.GetMediaAsynctask
|
import com.simplemobiletools.gallery.asynctasks.GetMediaAsynctask
|
||||||
import com.simplemobiletools.gallery.dialogs.SaveAsDialog
|
|
||||||
import com.simplemobiletools.gallery.extensions.*
|
import com.simplemobiletools.gallery.extensions.*
|
||||||
import com.simplemobiletools.gallery.fragments.PhotoFragment
|
import com.simplemobiletools.gallery.fragments.PhotoFragment
|
||||||
import com.simplemobiletools.gallery.fragments.ViewPagerFragment
|
import com.simplemobiletools.gallery.fragments.ViewPagerFragment
|
||||||
|
@ -35,7 +31,6 @@ import com.simplemobiletools.gallery.helpers.*
|
||||||
import com.simplemobiletools.gallery.models.Medium
|
import com.simplemobiletools.gallery.models.Medium
|
||||||
import kotlinx.android.synthetic.main.activity_medium.*
|
import kotlinx.android.synthetic.main.activity_medium.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.OutputStream
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, ViewPagerFragment.FragmentListener {
|
class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, ViewPagerFragment.FragmentListener {
|
||||||
|
@ -46,7 +41,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
||||||
private var mIsFullScreen = false
|
private var mIsFullScreen = false
|
||||||
private var mPos = -1
|
private var mPos = -1
|
||||||
private var mShowAll = false
|
private var mShowAll = false
|
||||||
private var mRotationDegrees = 0f
|
|
||||||
private var mLastHandledOrientation = 0
|
private var mLastHandledOrientation = 0
|
||||||
private var mPrevHashcode = 0
|
private var mPrevHashcode = 0
|
||||||
|
|
||||||
|
@ -187,16 +181,8 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
||||||
findItem(R.id.menu_set_as).isVisible = getCurrentMedium()!!.isImage() == true
|
findItem(R.id.menu_set_as).isVisible = getCurrentMedium()!!.isImage() == true
|
||||||
findItem(R.id.menu_edit).isVisible = getCurrentMedium()!!.isImage() == true
|
findItem(R.id.menu_edit).isVisible = getCurrentMedium()!!.isImage() == true
|
||||||
findItem(R.id.menu_rotate).isVisible = getCurrentMedium()!!.isImage() == true
|
findItem(R.id.menu_rotate).isVisible = getCurrentMedium()!!.isImage() == true
|
||||||
findItem(R.id.menu_save_as).isVisible = mRotationDegrees != 0f
|
|
||||||
findItem(R.id.menu_hide).isVisible = !getCurrentMedium()!!.name.startsWith('.')
|
findItem(R.id.menu_hide).isVisible = !getCurrentMedium()!!.name.startsWith('.')
|
||||||
findItem(R.id.menu_unhide).isVisible = getCurrentMedium()!!.name.startsWith('.')
|
findItem(R.id.menu_unhide).isVisible = getCurrentMedium()!!.name.startsWith('.')
|
||||||
|
|
||||||
findItem(R.id.menu_rotate).subMenu.apply {
|
|
||||||
clearHeader()
|
|
||||||
findItem(R.id.rotate_right).icon = resources.getColoredDrawable(R.drawable.ic_rotate_right, R.color.actionbar_menu_icon)
|
|
||||||
findItem(R.id.rotate_left).icon = resources.getColoredDrawable(R.drawable.ic_rotate_left, R.color.actionbar_menu_icon)
|
|
||||||
findItem(R.id.rotate_one_eighty).icon = resources.getColoredDrawable(R.drawable.ic_rotate_one_eighty, R.color.actionbar_menu_icon)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@ -218,11 +204,8 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
||||||
R.id.menu_rename -> renameFile()
|
R.id.menu_rename -> renameFile()
|
||||||
R.id.menu_edit -> openFileEditor(getCurrentFile())
|
R.id.menu_edit -> openFileEditor(getCurrentFile())
|
||||||
R.id.menu_properties -> showProperties()
|
R.id.menu_properties -> showProperties()
|
||||||
R.id.menu_save_as -> saveImageAs()
|
|
||||||
R.id.show_on_map -> showOnMap()
|
R.id.show_on_map -> showOnMap()
|
||||||
R.id.rotate_right -> rotateImage(90f)
|
R.id.menu_rotate -> rotateImage()
|
||||||
R.id.rotate_left -> rotateImage(-90f)
|
|
||||||
R.id.rotate_one_eighty -> rotateImage(180f)
|
|
||||||
R.id.settings -> launchSettings()
|
R.id.settings -> launchSettings()
|
||||||
else -> return super.onOptionsItemSelected(item)
|
else -> return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
@ -264,52 +247,23 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveImageAs() {
|
private fun rotateImage() {
|
||||||
val currPath = getCurrentPath()
|
val exif = ExifInterface(getCurrentPath())
|
||||||
SaveAsDialog(this, currPath) {
|
val rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
|
||||||
Thread({
|
val newRotation = getNewRotation(rotation)
|
||||||
toast(R.string.saving)
|
exif.setAttribute(ExifInterface.TAG_ORIENTATION, newRotation)
|
||||||
val selectedFile = File(it)
|
exif.saveAttributes()
|
||||||
val tmpFile = File(selectedFile.parent, "tmp_${it.getFilenameFromPath()}")
|
File(getCurrentPath()).setLastModified(System.currentTimeMillis())
|
||||||
try {
|
(getCurrentFragment() as? PhotoFragment)?.refreshBitmap()
|
||||||
val bitmap = BitmapFactory.decodeFile(currPath)
|
|
||||||
getFileOutputStream(tmpFile) {
|
|
||||||
saveFile(tmpFile, bitmap, it)
|
|
||||||
if (needsStupidWritePermissions(selectedFile.absolutePath)) {
|
|
||||||
deleteFile(selectedFile) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
renameFile(tmpFile, selectedFile) {
|
|
||||||
deleteFile(tmpFile) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: OutOfMemoryError) {
|
|
||||||
toast(R.string.out_of_memory_error)
|
|
||||||
deleteFile(tmpFile) {}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
toast(R.string.unknown_error_occurred)
|
|
||||||
deleteFile(tmpFile) {}
|
|
||||||
}
|
|
||||||
}).start()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveFile(file: File, bitmap: Bitmap, out: OutputStream) {
|
private fun getNewRotation(rotation: Int): String {
|
||||||
val matrix = Matrix()
|
return when (rotation) {
|
||||||
matrix.postRotate(mRotationDegrees)
|
ExifInterface.ORIENTATION_ROTATE_90 -> ExifInterface.ORIENTATION_ROTATE_180
|
||||||
val bmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
|
ExifInterface.ORIENTATION_ROTATE_180 -> ExifInterface.ORIENTATION_ROTATE_270
|
||||||
bmp.compress(file.getCompressionFormat(), 90, out)
|
ExifInterface.ORIENTATION_ROTATE_270 -> ExifInterface.ORIENTATION_NORMAL
|
||||||
out.flush()
|
else -> ExifInterface.ORIENTATION_ROTATE_90
|
||||||
toast(R.string.file_saved)
|
}.toString()
|
||||||
out.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun rotateImage(degrees: Float) {
|
|
||||||
mRotationDegrees = (mRotationDegrees + degrees) % 360
|
|
||||||
getCurrentFragment()?.let {
|
|
||||||
(it as? PhotoFragment)?.rotateImageViewBy(mRotationDegrees)
|
|
||||||
}
|
|
||||||
supportInvalidateOptionsMenu()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCurrentFragment() = (view_pager.adapter as MyPagerAdapter).getCurrentFragment(view_pager.currentItem)
|
private fun getCurrentFragment() = (view_pager.adapter as MyPagerAdapter).getCurrentFragment(view_pager.currentItem)
|
||||||
|
@ -536,7 +490,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
||||||
}
|
}
|
||||||
mPos = position
|
mPos = position
|
||||||
updateActionbarTitle()
|
updateActionbarTitle()
|
||||||
mRotationDegrees = 0f
|
|
||||||
supportInvalidateOptionsMenu()
|
supportInvalidateOptionsMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@ import com.simplemobiletools.gallery.extensions.config
|
||||||
import com.simplemobiletools.gallery.extensions.getFileSignature
|
import com.simplemobiletools.gallery.extensions.getFileSignature
|
||||||
import com.simplemobiletools.gallery.extensions.getRealPathFromURI
|
import com.simplemobiletools.gallery.extensions.getRealPathFromURI
|
||||||
import com.simplemobiletools.gallery.extensions.portrait
|
import com.simplemobiletools.gallery.extensions.portrait
|
||||||
import com.simplemobiletools.gallery.helpers.GlideRotateTransformation
|
|
||||||
import com.simplemobiletools.gallery.helpers.MEDIUM
|
import com.simplemobiletools.gallery.helpers.MEDIUM
|
||||||
import com.simplemobiletools.gallery.models.Medium
|
import com.simplemobiletools.gallery.models.Medium
|
||||||
import it.sephiroth.android.library.exif2.ExifInterface
|
import it.sephiroth.android.library.exif2.ExifInterface
|
||||||
|
@ -159,38 +158,28 @@ class PhotoFragment : ViewPagerFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadBitmap(degrees: Float = 0f) {
|
private fun loadBitmap() {
|
||||||
if (degrees == 0f) {
|
val targetWidth = if (ViewPagerActivity.screenWidth == 0) Target.SIZE_ORIGINAL else ViewPagerActivity.screenWidth
|
||||||
val targetWidth = if (ViewPagerActivity.screenWidth == 0) Target.SIZE_ORIGINAL else ViewPagerActivity.screenWidth
|
val targetHeight = if (ViewPagerActivity.screenHeight == 0) Target.SIZE_ORIGINAL else ViewPagerActivity.screenHeight
|
||||||
val targetHeight = if (ViewPagerActivity.screenHeight == 0) Target.SIZE_ORIGINAL else ViewPagerActivity.screenHeight
|
|
||||||
|
|
||||||
Glide.with(this)
|
Glide.with(this)
|
||||||
.load(medium.path)
|
.load(medium.path)
|
||||||
.asBitmap()
|
.asBitmap()
|
||||||
.signature(activity.getFileSignature(medium.path))
|
.signature(activity.getFileSignature(medium.path))
|
||||||
.format(if (medium.isPng()) DecodeFormat.PREFER_ARGB_8888 else DecodeFormat.PREFER_RGB_565)
|
.format(if (medium.isPng()) DecodeFormat.PREFER_ARGB_8888 else DecodeFormat.PREFER_RGB_565)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.override(targetWidth, targetHeight)
|
.override(targetWidth, targetHeight)
|
||||||
.listener(object : RequestListener<String, Bitmap> {
|
.listener(object : RequestListener<String, Bitmap> {
|
||||||
override fun onException(e: Exception?, model: String?, target: Target<Bitmap>?, isFirstResource: Boolean): Boolean {
|
override fun onException(e: Exception?, model: String?, target: Target<Bitmap>?, isFirstResource: Boolean): Boolean {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResourceReady(resource: Bitmap, model: String?, target: Target<Bitmap>?, isFromMemoryCache: Boolean, isFirstResource: Boolean): Boolean {
|
override fun onResourceReady(resource: Bitmap, model: String?, target: Target<Bitmap>?, isFromMemoryCache: Boolean, isFirstResource: Boolean): Boolean {
|
||||||
if (isFragmentVisible)
|
if (isFragmentVisible)
|
||||||
addZoomableView()
|
addZoomableView()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}).into(view.photo_view)
|
}).into(view.photo_view)
|
||||||
} else {
|
|
||||||
Glide.with(this)
|
|
||||||
.load(medium.path)
|
|
||||||
.asBitmap()
|
|
||||||
.transform(GlideRotateTransformation(context, degrees))
|
|
||||||
.thumbnail(0.2f)
|
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
|
||||||
.into(view.photo_view)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addZoomableView() {
|
private fun addZoomableView() {
|
||||||
|
@ -249,16 +238,16 @@ class PhotoFragment : ViewPagerFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun refreshBitmap() {
|
||||||
|
view.subsampling_view.beGone()
|
||||||
|
loadBitmap()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
Glide.clear(view.photo_view)
|
Glide.clear(view.photo_view)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun rotateImageViewBy(degrees: Float) {
|
|
||||||
view.subsampling_view.beGone()
|
|
||||||
loadBitmap(degrees)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onConfigurationChanged(newConfig: Configuration?) {
|
override fun onConfigurationChanged(newConfig: Configuration?) {
|
||||||
super.onConfigurationChanged(newConfig)
|
super.onConfigurationChanged(newConfig)
|
||||||
loadImage()
|
loadImage()
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
package com.simplemobiletools.gallery.helpers
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.graphics.Matrix
|
|
||||||
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
|
|
||||||
|
|
||||||
class GlideRotateTransformation(context: Context, val rotateRotationAngle: Float) : BitmapTransformation(context) {
|
|
||||||
|
|
||||||
override fun transform(pool: BitmapPool, bitmap: Bitmap, outWidth: Int, outHeight: Int): Bitmap {
|
|
||||||
if (rotateRotationAngle % 360 == 0f)
|
|
||||||
return bitmap
|
|
||||||
|
|
||||||
val matrix = Matrix()
|
|
||||||
matrix.postRotate(rotateRotationAngle)
|
|
||||||
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getId() = "GlideRotateTransformation $rotateRotationAngle"
|
|
||||||
}
|
|
|
@ -5,24 +5,6 @@
|
||||||
android:id="@+id/menu_rotate"
|
android:id="@+id/menu_rotate"
|
||||||
android:icon="@drawable/ic_rotate_right"
|
android:icon="@drawable/ic_rotate_right"
|
||||||
android:title="@string/rotate"
|
android:title="@string/rotate"
|
||||||
app:showAsAction="ifRoom">
|
|
||||||
<menu>
|
|
||||||
<item
|
|
||||||
android:id="@+id/rotate_right"
|
|
||||||
android:title="@string/rotate_right"/>
|
|
||||||
<item
|
|
||||||
android:id="@+id/rotate_left"
|
|
||||||
android:title="@string/rotate_left"/>
|
|
||||||
<item
|
|
||||||
android:id="@+id/rotate_one_eighty"
|
|
||||||
android:title="@string/rotate_one_eighty"/>
|
|
||||||
</menu>
|
|
||||||
</item>
|
|
||||||
<item
|
|
||||||
android:id="@+id/menu_save_as"
|
|
||||||
android:icon="@drawable/ic_check"
|
|
||||||
android:title="@string/save_as"
|
|
||||||
android:visible="false"
|
|
||||||
app:showAsAction="ifRoom"/>
|
app:showAsAction="ifRoom"/>
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_delete"
|
android:id="@+id/menu_delete"
|
||||||
|
|
Loading…
Reference in a new issue