try improving the image loading performance on weaker devices

This commit is contained in:
tibbi 2019-08-11 12:10:13 +02:00
parent f2b41a3758
commit a66596f160
3 changed files with 27 additions and 9 deletions

View file

@ -251,7 +251,6 @@ class PhotoFragment : ViewPagerFragment() {
override fun onConfigurationChanged(newConfig: Configuration) { override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig) super.onConfigurationChanged(newConfig)
if (!mWasInit) { if (!mWasInit) {
return return
} }
@ -272,6 +271,7 @@ class PhotoFragment : ViewPagerFragment() {
loadImage() loadImage()
} }
measureScreen()
initExtendedDetails() initExtendedDetails()
updateInstantSwitchWidths() updateInstantSwitchWidths()
} }
@ -461,13 +461,14 @@ class PhotoFragment : ViewPagerFragment() {
mIsSubsamplingVisible = true mIsSubsamplingVisible = true
val config = context!!.config val config = context!!.config
val showHighestQuality = config.showHighestQuality val showHighestQuality = config.showHighestQuality
val minTileDpi = if (showHighestQuality) -1 else getMinTileDpi()
val bitmapDecoder = object : DecoderFactory<ImageDecoder> { val bitmapDecoder = object : DecoderFactory<ImageDecoder> {
override fun make() = PicassoDecoder(mMedium.path, Picasso.get(), rotation) override fun make() = PicassoDecoder(mMedium.path, Picasso.get(), rotation)
} }
val regionDecoder = object : DecoderFactory<ImageRegionDecoder> { val regionDecoder = object : DecoderFactory<ImageRegionDecoder> {
override fun make() = PicassoRegionDecoder(showHighestQuality) override fun make() = PicassoRegionDecoder(showHighestQuality, mScreenWidth, mScreenHeight, minTileDpi)
} }
var newOrientation = (rotation + mCurrentRotationDegrees) % 360 var newOrientation = (rotation + mCurrentRotationDegrees) % 360
@ -477,7 +478,7 @@ class PhotoFragment : ViewPagerFragment() {
mView.subsampling_view.apply { mView.subsampling_view.apply {
setMaxTileSize(if (showHighestQuality) Integer.MAX_VALUE else 4096) setMaxTileSize(if (showHighestQuality) Integer.MAX_VALUE else 4096)
setMinimumTileDpi(if (showHighestQuality) -1 else getMinTileDpi()) setMinimumTileDpi(minTileDpi)
background = ColorDrawable(Color.TRANSPARENT) background = ColorDrawable(Color.TRANSPARENT)
bitmapDecoderFactory = bitmapDecoder bitmapDecoderFactory = bitmapDecoder
regionDecoderFactory = regionDecoder regionDecoderFactory = regionDecoder
@ -487,6 +488,7 @@ class PhotoFragment : ViewPagerFragment() {
isOneToOneZoomEnabled = config.allowOneToOneZoom isOneToOneZoomEnabled = config.allowOneToOneZoom
orientation = newOrientation orientation = newOrientation
setImage(mMedium.path) setImage(mMedium.path)
onImageEventListener = object : SubsamplingScaleImageView.OnImageEventListener { onImageEventListener = object : SubsamplingScaleImageView.OnImageEventListener {
override fun onReady() { override fun onReady() {
background = ColorDrawable(if (config.blackBackground) Color.BLACK else config.backgroundColor) background = ColorDrawable(if (config.blackBackground) Color.BLACK else config.backgroundColor)
@ -520,10 +522,10 @@ class PhotoFragment : ViewPagerFragment() {
val averageDpi = (metrics.xdpi + metrics.ydpi) / 2 val averageDpi = (metrics.xdpi + metrics.ydpi) / 2
val device = "${Build.BRAND} ${Build.MODEL}".toLowerCase() val device = "${Build.BRAND} ${Build.MODEL}".toLowerCase()
return when { return when {
WEIRD_DEVICES.contains(device) -> 240 WEIRD_DEVICES.contains(device) -> WEIRD_TILE_DPI
averageDpi > 400 -> 280 averageDpi > 400 -> HIGH_TILE_DPI
averageDpi > 300 -> 220 averageDpi > 300 -> NORMAL_TILE_DPI
else -> 160 else -> LOW_TILE_DPI
} }
} }

View file

@ -208,3 +208,9 @@ const val MAX_VIDEO_ZOOM_SCALE = 5f
const val ZOOM_MODE_NONE = 0 const val ZOOM_MODE_NONE = 0
const val ZOOM_MODE_DRAG = 1 const val ZOOM_MODE_DRAG = 1
const val ZOOM_MODE_ZOOM = 2 const val ZOOM_MODE_ZOOM = 2
// constants related to image quality
const val LOW_TILE_DPI = 160
const val NORMAL_TILE_DPI = 220
const val WEIRD_TILE_DPI = 240
const val HIGH_TILE_DPI = 280

View file

@ -5,7 +5,7 @@ import android.graphics.*
import android.net.Uri import android.net.Uri
import com.davemorrissey.labs.subscaleview.ImageRegionDecoder import com.davemorrissey.labs.subscaleview.ImageRegionDecoder
class PicassoRegionDecoder(val showHighestQuality: Boolean) : ImageRegionDecoder { class PicassoRegionDecoder(val showHighestQuality: Boolean, val screenWidth: Int, val screenHeight: Int, val minTileDpi: Int) : ImageRegionDecoder {
private var decoder: BitmapRegionDecoder? = null private var decoder: BitmapRegionDecoder? = null
private val decoderLock = Any() private val decoderLock = Any()
@ -18,10 +18,20 @@ class PicassoRegionDecoder(val showHighestQuality: Boolean) : ImageRegionDecoder
override fun decodeRegion(rect: Rect, sampleSize: Int): Bitmap { override fun decodeRegion(rect: Rect, sampleSize: Int): Bitmap {
synchronized(decoderLock) { synchronized(decoderLock) {
var newSampleSize = sampleSize
if (!showHighestQuality && minTileDpi == LOW_TILE_DPI) {
if ((rect.width() > rect.height() && screenWidth > screenHeight) || (rect.height() > rect.width() && screenHeight > screenWidth)) {
if ((rect.width() / sampleSize > screenWidth || rect.height() / sampleSize > screenHeight)) {
newSampleSize *= 2
}
}
}
val options = BitmapFactory.Options() val options = BitmapFactory.Options()
options.inSampleSize = sampleSize options.inSampleSize = newSampleSize
options.inPreferredConfig = if (showHighestQuality) Bitmap.Config.ARGB_8888 else Bitmap.Config.RGB_565 options.inPreferredConfig = if (showHighestQuality) Bitmap.Config.ARGB_8888 else Bitmap.Config.RGB_565
val bitmap = decoder!!.decodeRegion(rect, options) val bitmap = decoder!!.decodeRegion(rect, options)
return bitmap ?: throw RuntimeException("Region decoder returned null bitmap - image format may not be supported") return bitmap ?: throw RuntimeException("Region decoder returned null bitmap - image format may not be supported")
} }
} }