diff --git a/app/build.gradle b/app/build.gradle
index 08ee360c4..0380deccc 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -132,7 +132,7 @@ dependencies {
implementation 'io.coil-kt:coil-base:2.4.0'
implementation 'io.coil-kt:coil-svg:2.4.0'
- implementation 'com.github.KotatsuApp:subsampling-scale-image-view:169806d928'
+ implementation 'com.github.KotatsuApp:subsampling-scale-image-view:cf089a264d'
implementation 'com.github.solkin:disk-lru-cache:1.4'
implementation 'io.noties.markwon:core:4.6.2'
diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt
index 71e7f91c7..dbee8c95c 100644
--- a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt
+++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt
@@ -336,6 +336,9 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
return policy.isNetworkAllowed(connectivityManager)
}
+ val is32BitColorsEnabled: Boolean
+ get() = prefs.getBoolean(KEY_32BIT_COLOR, false)
+
fun isTipEnabled(tip: String): Boolean {
return prefs.getStringSet(KEY_TIPS_CLOSED, emptySet())?.contains(tip) != true
}
@@ -491,6 +494,7 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
const val KEY_DISABLE_NSFW = "no_nsfw"
const val KEY_RELATED_MANGA = "related_manga"
const val KEY_NAV_MAIN = "nav_main"
+ const val KEY_32BIT_COLOR = "enhanced_colors"
// About
const val KEY_APP_UPDATE = "app_update"
diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderSettings.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderSettings.kt
index 354c7e528..083f3f3fb 100644
--- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderSettings.kt
+++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderSettings.kt
@@ -1,8 +1,14 @@
package org.koitharu.kotatsu.reader.ui.config
import android.content.SharedPreferences
+import android.graphics.Bitmap
import android.view.View
+import androidx.annotation.CheckResult
import androidx.lifecycle.MediatorLiveData
+import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
+import com.davemorrissey.labs.subscaleview.decoder.SkiaImageDecoder
+import com.davemorrissey.labs.subscaleview.decoder.SkiaImageRegionDecoder
+import com.davemorrissey.labs.subscaleview.decoder.SkiaPooledImageRegionDecoder
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@@ -12,6 +18,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koitharu.kotatsu.core.model.ZoomMode
import org.koitharu.kotatsu.core.prefs.AppSettings
+import org.koitharu.kotatsu.core.util.ext.isLowRamDevice
import org.koitharu.kotatsu.reader.domain.ReaderColorFilter
class ReaderSettings(
@@ -29,6 +36,13 @@ class ReaderSettings(
val colorFilter: ReaderColorFilter?
get() = colorFilterFlow.value?.takeUnless { it.isEmpty }
+ val bitmapConfig: Bitmap.Config
+ get() = if (settings.is32BitColorsEnabled) {
+ Bitmap.Config.ARGB_8888
+ } else {
+ Bitmap.Config.RGB_565
+ }
+
val isPagesNumbersEnabled: Boolean
get() = settings.isPagesNumbersEnabled
@@ -40,6 +54,22 @@ class ReaderSettings(
view.background = bg.resolve(view.context)
}
+ @CheckResult
+ fun applyBitmapConfig(ssiv: SubsamplingScaleImageView): Boolean {
+ val config = bitmapConfig
+ return if (ssiv.regionDecoderFactory.bitmapConfig != config) {
+ ssiv.regionDecoderFactory = if (ssiv.context.isLowRamDevice()) {
+ SkiaImageRegionDecoder.Factory(config)
+ } else {
+ SkiaPooledImageRegionDecoder.Factory(config)
+ }
+ ssiv.bitmapDecoderFactory = SkiaImageDecoder.Factory(config)
+ true
+ } else {
+ false
+ }
+ }
+
override fun onInactive() {
super.onInactive()
settings.unsubscribe(internalObserver)
@@ -78,7 +108,8 @@ class ReaderSettings(
key == AppSettings.KEY_PAGES_NUMBERS ||
key == AppSettings.KEY_WEBTOON_ZOOM ||
key == AppSettings.KEY_READER_ZOOM_BUTTONS ||
- key == AppSettings.KEY_READER_BACKGROUND
+ key == AppSettings.KEY_READER_BACKGROUND ||
+ key == AppSettings.KEY_32BIT_COLOR
) {
notifyChanged()
}
diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/PageHolderDelegate.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/PageHolderDelegate.kt
index d874a12b1..9ac31c5f8 100644
--- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/PageHolderDelegate.kt
+++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/PageHolderDelegate.kt
@@ -84,6 +84,14 @@ class PageHolderDelegate(
job?.cancel()
}
+ fun reload() {
+ if (state == State.SHOWN ) {
+ file?.let {
+ callback.onImageReady(it.toUri())
+ }
+ }
+ }
+
override fun onReady() {
state = State.SHOWING
error = null
diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt
index b7ea73e76..6882bf874 100644
--- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt
+++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt
@@ -46,6 +46,10 @@ open class PageHolder(
override fun onConfigChanged() {
super.onConfigChanged()
binding.zoomControl.isVisible = settings.isZoomControlsEnabled
+ @Suppress("SENSELESS_COMPARISON")
+ if (settings.applyBitmapConfig(binding.ssiv) && delegate != null) {
+ delegate.reload()
+ }
}
@SuppressLint("SetTextI18n")
diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt
index f5a936ad6..d2edc326a 100644
--- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt
+++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt
@@ -6,7 +6,6 @@ import androidx.core.view.isVisible
import androidx.lifecycle.LifecycleOwner
import com.davemorrissey.labs.subscaleview.ImageSource
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
-import com.davemorrissey.labs.subscaleview.decoder.SkiaPooledImageRegionDecoder
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
import org.koitharu.kotatsu.core.os.NetworkState
@@ -34,12 +33,19 @@ class WebtoonHolder(
init {
binding.ssiv.bindToLifecycle(owner)
- binding.ssiv.regionDecoderFactory = SkiaPooledImageRegionDecoder.Factory()
binding.ssiv.addOnImageEventListener(delegate)
bindingInfo.buttonRetry.setOnClickListener(this)
bindingInfo.buttonErrorDetails.setOnClickListener(this)
}
+ override fun onConfigChanged() {
+ super.onConfigChanged()
+ @Suppress("SENSELESS_COMPARISON")
+ if (settings.applyBitmapConfig(binding.ssiv) && delegate != null) {
+ delegate.reload()
+ }
+ }
+
override fun onBind(data: ReaderPage) {
delegate.onBind(data.toMangaPage())
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f742238df..49eed5c50 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -492,4 +492,6 @@
Keep screen on
Do not turn the screen off while you\'re reading manga
Dropped
+ Reduces banding, but may impact performance
+ 32-bit color mode
diff --git a/app/src/main/res/xml/pref_reader.xml b/app/src/main/res/xml/pref_reader.xml
index 0ae86ab91..57b460aac 100644
--- a/app/src/main/res/xml/pref_reader.xml
+++ b/app/src/main/res/xml/pref_reader.xml
@@ -54,6 +54,12 @@
android:title="@string/pages_animation"
app:useSimpleSummaryProvider="true" />
+
+