mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-20 03:59:35 +01:00
Merge pull request #1283 from nextcloud/bug/1190/fixHdImageDisplay
fix displaying of large images
This commit is contained in:
commit
6c0160f197
@ -186,6 +186,7 @@ dependencies {
|
||||
implementation "androidx.work:work-runtime:${workVersion}"
|
||||
implementation "androidx.work:work-rxjava2:${workVersion}"
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||
implementation 'androidx.exifinterface:exifinterface:1.3.2'
|
||||
androidTestImplementation "androidx.work:work-testing:${workVersion}"
|
||||
implementation 'com.google.android:flexbox:2.0.1'
|
||||
implementation ('com.gitlab.bitfireAT:dav4jvm:2.1.2', {
|
||||
|
@ -25,29 +25,26 @@
|
||||
package com.nextcloud.talk.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.FileProvider
|
||||
import com.nextcloud.talk.BuildConfig
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.databinding.ActivityFullScreenImageBinding
|
||||
import com.nextcloud.talk.utils.BitmapShrinker
|
||||
import pl.droidsonroids.gif.GifDrawable
|
||||
import java.io.File
|
||||
|
||||
class FullScreenImageActivity : AppCompatActivity() {
|
||||
lateinit var binding: ActivityFullScreenImageBinding
|
||||
|
||||
private lateinit var path: String
|
||||
|
||||
private var showFullscreen = false
|
||||
|
||||
private val maxScale = 6.0f
|
||||
private val mediumScale = 2.45f
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_preview, menu)
|
||||
return true
|
||||
@ -98,8 +95,8 @@ class FullScreenImageActivity : AppCompatActivity() {
|
||||
|
||||
// Enable enlarging the image more than default 3x maximumScale.
|
||||
// Medium scale adapted to make double-tap behaviour more consistent.
|
||||
binding.photoView.maximumScale = maxScale
|
||||
binding.photoView.mediumScale = mediumScale
|
||||
binding.photoView.maximumScale = MAX_SCALE
|
||||
binding.photoView.mediumScale = MEDIUM_SCALE
|
||||
|
||||
val fileName = intent.getStringExtra("FILE_NAME")
|
||||
val isGif = intent.getBooleanExtra("IS_GIF", false)
|
||||
@ -116,7 +113,25 @@ class FullScreenImageActivity : AppCompatActivity() {
|
||||
} else {
|
||||
binding.gifView.visibility = View.INVISIBLE
|
||||
binding.photoView.visibility = View.VISIBLE
|
||||
binding.photoView.setImageURI(Uri.parse(path))
|
||||
displayImage(path)
|
||||
}
|
||||
}
|
||||
|
||||
private fun displayImage(path: String) {
|
||||
val displayMetrics = applicationContext.resources.displayMetrics
|
||||
val doubleScreenWidth = displayMetrics.widthPixels * 2
|
||||
val doubleScreenHeight = displayMetrics.heightPixels * 2
|
||||
|
||||
val bitmap = BitmapShrinker.shrinkBitmap(path, doubleScreenWidth, doubleScreenHeight)
|
||||
|
||||
val bitmapSize: Int = bitmap.byteCount
|
||||
|
||||
// info that 100MB is the limit comes from https://stackoverflow.com/a/53334563
|
||||
if (bitmapSize > HUNDRED_MB) {
|
||||
Log.e(TAG, "bitmap will be too large to display. It won't be displayed to avoid RuntimeException")
|
||||
Toast.makeText(this, R.string.nc_common_error_sorry, Toast.LENGTH_LONG).show()
|
||||
} else {
|
||||
binding.photoView.setImageBitmap(bitmap)
|
||||
}
|
||||
}
|
||||
|
||||
@ -149,4 +164,11 @@ class FullScreenImageActivity : AppCompatActivity() {
|
||||
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = "FullScreenImageActivity"
|
||||
private const val HUNDRED_MB = 100 * 1024 * 1024
|
||||
private const val MAX_SCALE = 6.0f
|
||||
private const val MEDIUM_SCALE = 2.45f
|
||||
}
|
||||
}
|
||||
|
112
app/src/main/java/com/nextcloud/talk/utils/BitmapShrinker.kt
Normal file
112
app/src/main/java/com/nextcloud/talk/utils/BitmapShrinker.kt
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Marcel Hibbe
|
||||
* Copyright (C) 2021 Marcel Hibbe <dev@mhibbe.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.utils
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Matrix
|
||||
import android.util.Log
|
||||
import androidx.exifinterface.media.ExifInterface
|
||||
import java.io.IOException
|
||||
|
||||
object BitmapShrinker {
|
||||
|
||||
private val TAG = "BitmapShrinker"
|
||||
private const val DEGREES_90 = 90f
|
||||
private const val DEGREES_180 = 180f
|
||||
private const val DEGREES_270 = 270f
|
||||
|
||||
fun shrinkBitmap(
|
||||
path: String,
|
||||
reqWidth: Int,
|
||||
reqHeight: Int
|
||||
): Bitmap {
|
||||
val bitmap = decodeBitmap(path, reqWidth, reqHeight)
|
||||
return rotateBitmap(path, bitmap)
|
||||
}
|
||||
|
||||
// solution inspired by https://developer.android.com/topic/performance/graphics/load-bitmap
|
||||
private fun decodeBitmap(
|
||||
path: String,
|
||||
requestedWidth: Int,
|
||||
requestedHeight: Int
|
||||
): Bitmap {
|
||||
return BitmapFactory.Options().run {
|
||||
inJustDecodeBounds = true
|
||||
BitmapFactory.decodeFile(path, this)
|
||||
inSampleSize = getInSampleSize(this, requestedWidth, requestedHeight)
|
||||
inJustDecodeBounds = false
|
||||
BitmapFactory.decodeFile(path, this)
|
||||
}
|
||||
}
|
||||
|
||||
// solution inspired by https://developer.android.com/topic/performance/graphics/load-bitmap
|
||||
private fun getInSampleSize(
|
||||
options: BitmapFactory.Options,
|
||||
requestedWidth: Int,
|
||||
requestedHeight: Int
|
||||
): Int {
|
||||
val (height: Int, width: Int) = options.run { outHeight to outWidth }
|
||||
var inSampleSize = 1
|
||||
if (height > requestedHeight || width > requestedWidth) {
|
||||
val halfHeight: Int = height / 2
|
||||
val halfWidth: Int = width / 2
|
||||
// "||" was used instead of "&&". Otherwise it would still crash for wide panorama photos.
|
||||
while (halfHeight / inSampleSize >= requestedHeight || halfWidth / inSampleSize >= requestedWidth) {
|
||||
inSampleSize *= 2
|
||||
}
|
||||
}
|
||||
return inSampleSize
|
||||
}
|
||||
|
||||
// solution inspired by https://stackoverflow.com/a/15341203
|
||||
private fun rotateBitmap(path: String, bitmap: Bitmap): Bitmap {
|
||||
try {
|
||||
val exif = ExifInterface(path)
|
||||
val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1)
|
||||
val matrix = Matrix()
|
||||
when (orientation) {
|
||||
ExifInterface.ORIENTATION_ROTATE_90 -> {
|
||||
matrix.postRotate(DEGREES_90)
|
||||
}
|
||||
ExifInterface.ORIENTATION_ROTATE_180 -> {
|
||||
matrix.postRotate(DEGREES_180)
|
||||
}
|
||||
ExifInterface.ORIENTATION_ROTATE_270 -> {
|
||||
matrix.postRotate(DEGREES_270)
|
||||
}
|
||||
}
|
||||
val rotatedBitmap = Bitmap.createBitmap(
|
||||
bitmap,
|
||||
0,
|
||||
0,
|
||||
bitmap.getWidth(),
|
||||
bitmap.getHeight(),
|
||||
matrix,
|
||||
true
|
||||
)
|
||||
return rotatedBitmap
|
||||
} catch (e: IOException) {
|
||||
Log.e(TAG, "error while rotating image", e)
|
||||
}
|
||||
return bitmap
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user