mirror of
https://github.com/FossifyOrg/Gallery.git
synced 2024-11-26 14:37:59 +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.res.Configuration
|
||||
import android.database.Cursor
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Color
|
||||
import android.graphics.Matrix
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.hardware.SensorManager
|
||||
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.adapters.MyPagerAdapter
|
||||
import com.simplemobiletools.gallery.asynctasks.GetMediaAsynctask
|
||||
import com.simplemobiletools.gallery.dialogs.SaveAsDialog
|
||||
import com.simplemobiletools.gallery.extensions.*
|
||||
import com.simplemobiletools.gallery.fragments.PhotoFragment
|
||||
import com.simplemobiletools.gallery.fragments.ViewPagerFragment
|
||||
|
@ -35,7 +31,6 @@ 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.util.*
|
||||
|
||||
class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, ViewPagerFragment.FragmentListener {
|
||||
|
@ -46,7 +41,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
private var mIsFullScreen = false
|
||||
private var mPos = -1
|
||||
private var mShowAll = false
|
||||
private var mRotationDegrees = 0f
|
||||
private var mLastHandledOrientation = 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_edit).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_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
|
||||
|
@ -218,11 +204,8 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
R.id.menu_rename -> renameFile()
|
||||
R.id.menu_edit -> openFileEditor(getCurrentFile())
|
||||
R.id.menu_properties -> showProperties()
|
||||
R.id.menu_save_as -> saveImageAs()
|
||||
R.id.show_on_map -> showOnMap()
|
||||
R.id.rotate_right -> rotateImage(90f)
|
||||
R.id.rotate_left -> rotateImage(-90f)
|
||||
R.id.rotate_one_eighty -> rotateImage(180f)
|
||||
R.id.menu_rotate -> rotateImage()
|
||||
R.id.settings -> launchSettings()
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
@ -264,52 +247,23 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
}
|
||||
}
|
||||
|
||||
private fun saveImageAs() {
|
||||
val currPath = getCurrentPath()
|
||||
SaveAsDialog(this, currPath) {
|
||||
Thread({
|
||||
toast(R.string.saving)
|
||||
val selectedFile = File(it)
|
||||
val tmpFile = File(selectedFile.parent, "tmp_${it.getFilenameFromPath()}")
|
||||
try {
|
||||
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 rotateImage() {
|
||||
val exif = ExifInterface(getCurrentPath())
|
||||
val rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
|
||||
val newRotation = getNewRotation(rotation)
|
||||
exif.setAttribute(ExifInterface.TAG_ORIENTATION, newRotation)
|
||||
exif.saveAttributes()
|
||||
File(getCurrentPath()).setLastModified(System.currentTimeMillis())
|
||||
(getCurrentFragment() as? PhotoFragment)?.refreshBitmap()
|
||||
}
|
||||
|
||||
private fun saveFile(file: File, bitmap: Bitmap, out: OutputStream) {
|
||||
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()
|
||||
toast(R.string.file_saved)
|
||||
out.close()
|
||||
}
|
||||
|
||||
private fun rotateImage(degrees: Float) {
|
||||
mRotationDegrees = (mRotationDegrees + degrees) % 360
|
||||
getCurrentFragment()?.let {
|
||||
(it as? PhotoFragment)?.rotateImageViewBy(mRotationDegrees)
|
||||
}
|
||||
supportInvalidateOptionsMenu()
|
||||
private fun getNewRotation(rotation: Int): String {
|
||||
return when (rotation) {
|
||||
ExifInterface.ORIENTATION_ROTATE_90 -> ExifInterface.ORIENTATION_ROTATE_180
|
||||
ExifInterface.ORIENTATION_ROTATE_180 -> ExifInterface.ORIENTATION_ROTATE_270
|
||||
ExifInterface.ORIENTATION_ROTATE_270 -> ExifInterface.ORIENTATION_NORMAL
|
||||
else -> ExifInterface.ORIENTATION_ROTATE_90
|
||||
}.toString()
|
||||
}
|
||||
|
||||
private fun getCurrentFragment() = (view_pager.adapter as MyPagerAdapter).getCurrentFragment(view_pager.currentItem)
|
||||
|
@ -536,7 +490,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
|
|||
}
|
||||
mPos = position
|
||||
updateActionbarTitle()
|
||||
mRotationDegrees = 0f
|
||||
supportInvalidateOptionsMenu()
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ import com.simplemobiletools.gallery.extensions.config
|
|||
import com.simplemobiletools.gallery.extensions.getFileSignature
|
||||
import com.simplemobiletools.gallery.extensions.getRealPathFromURI
|
||||
import com.simplemobiletools.gallery.extensions.portrait
|
||||
import com.simplemobiletools.gallery.helpers.GlideRotateTransformation
|
||||
import com.simplemobiletools.gallery.helpers.MEDIUM
|
||||
import com.simplemobiletools.gallery.models.Medium
|
||||
import it.sephiroth.android.library.exif2.ExifInterface
|
||||
|
@ -159,38 +158,28 @@ class PhotoFragment : ViewPagerFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun loadBitmap(degrees: Float = 0f) {
|
||||
if (degrees == 0f) {
|
||||
val targetWidth = if (ViewPagerActivity.screenWidth == 0) Target.SIZE_ORIGINAL else ViewPagerActivity.screenWidth
|
||||
val targetHeight = if (ViewPagerActivity.screenHeight == 0) Target.SIZE_ORIGINAL else ViewPagerActivity.screenHeight
|
||||
private fun loadBitmap() {
|
||||
val targetWidth = if (ViewPagerActivity.screenWidth == 0) Target.SIZE_ORIGINAL else ViewPagerActivity.screenWidth
|
||||
val targetHeight = if (ViewPagerActivity.screenHeight == 0) Target.SIZE_ORIGINAL else ViewPagerActivity.screenHeight
|
||||
|
||||
Glide.with(this)
|
||||
.load(medium.path)
|
||||
.asBitmap()
|
||||
.signature(activity.getFileSignature(medium.path))
|
||||
.format(if (medium.isPng()) DecodeFormat.PREFER_ARGB_8888 else DecodeFormat.PREFER_RGB_565)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.override(targetWidth, targetHeight)
|
||||
.listener(object : RequestListener<String, Bitmap> {
|
||||
override fun onException(e: Exception?, model: String?, target: Target<Bitmap>?, isFirstResource: Boolean): Boolean {
|
||||
return false
|
||||
}
|
||||
Glide.with(this)
|
||||
.load(medium.path)
|
||||
.asBitmap()
|
||||
.signature(activity.getFileSignature(medium.path))
|
||||
.format(if (medium.isPng()) DecodeFormat.PREFER_ARGB_8888 else DecodeFormat.PREFER_RGB_565)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.override(targetWidth, targetHeight)
|
||||
.listener(object : RequestListener<String, Bitmap> {
|
||||
override fun onException(e: Exception?, model: String?, target: Target<Bitmap>?, isFirstResource: Boolean): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onResourceReady(resource: Bitmap, model: String?, target: Target<Bitmap>?, isFromMemoryCache: Boolean, isFirstResource: Boolean): Boolean {
|
||||
if (isFragmentVisible)
|
||||
addZoomableView()
|
||||
return false
|
||||
}
|
||||
}).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)
|
||||
}
|
||||
override fun onResourceReady(resource: Bitmap, model: String?, target: Target<Bitmap>?, isFromMemoryCache: Boolean, isFirstResource: Boolean): Boolean {
|
||||
if (isFragmentVisible)
|
||||
addZoomableView()
|
||||
return false
|
||||
}
|
||||
}).into(view.photo_view)
|
||||
}
|
||||
|
||||
private fun addZoomableView() {
|
||||
|
@ -249,16 +238,16 @@ class PhotoFragment : ViewPagerFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
fun refreshBitmap() {
|
||||
view.subsampling_view.beGone()
|
||||
loadBitmap()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
Glide.clear(view.photo_view)
|
||||
}
|
||||
|
||||
fun rotateImageViewBy(degrees: Float) {
|
||||
view.subsampling_view.beGone()
|
||||
loadBitmap(degrees)
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration?) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
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:icon="@drawable/ic_rotate_right"
|
||||
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"/>
|
||||
<item
|
||||
android:id="@+id/menu_delete"
|
||||
|
|
Loading…
Reference in a new issue