From 817ce7e8dfc5f55679ed2f506a7195327758767e Mon Sep 17 00:00:00 2001 From: Zakhar Timoshenko Date: Wed, 11 Oct 2023 21:18:13 +0300 Subject: [PATCH 1/3] 32-bit colors mode implementing --- .../koitharu/kotatsu/core/prefs/AppSettings.kt | 4 ++++ .../kotatsu/reader/ui/config/ReaderSettings.kt | 18 +++++++++++++++++- .../reader/ui/pager/standard/PageHolder.kt | 3 +++ app/src/main/res/values/strings.xml | 2 ++ app/src/main/res/xml/pref_reader.xml | 6 ++++++ 5 files changed, 32 insertions(+), 1 deletion(-) 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..e0ee582b5 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 enhancedColors: 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..cd2189de6 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,11 @@ package org.koitharu.kotatsu.reader.ui.config import android.content.SharedPreferences +import android.graphics.Bitmap import android.view.View import androidx.lifecycle.MediatorLiveData +import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView +import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView.Companion.preferredBitmapConfig import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -29,6 +32,9 @@ class ReaderSettings( val colorFilter: ReaderColorFilter? get() = colorFilterFlow.value?.takeUnless { it.isEmpty } + val enhancedColors: Boolean + get() = settings.enhancedColors + val isPagesNumbersEnabled: Boolean get() = settings.isPagesNumbersEnabled @@ -40,6 +46,15 @@ class ReaderSettings( view.background = bg.resolve(view.context) } + fun enhancedColorsMode() { + val modeEnabled = settings.enhancedColors + preferredBitmapConfig = if (modeEnabled) { + Bitmap.Config.ARGB_8888 + } else { + Bitmap.Config.RGB_565 + } + } + override fun onInactive() { super.onInactive() settings.unsubscribe(internalObserver) @@ -78,7 +93,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/standard/PageHolder.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/standard/PageHolder.kt index b7ea73e76..39fbc9c77 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 @@ -4,10 +4,12 @@ import android.annotation.SuppressLint import android.graphics.PointF import android.net.Uri import android.view.View +import androidx.core.view.drawToBitmap 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.SubsamplingScaleImageView.Companion.preferredBitmapConfig import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.model.ZoomMode @@ -84,6 +86,7 @@ open class PageHolder( binding.ssiv.height / binding.ssiv.sHeight.toFloat(), ) binding.ssiv.colorFilter = settings.colorFilter?.toColorFilter() + settings.enhancedColorsMode() when (settings.zoomMode) { ZoomMode.FIT_CENTER -> { binding.ssiv.minimumScaleType = SubsamplingScaleImageView.SCALE_TYPE_CENTER_INSIDE 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" /> + + Date: Thu, 12 Oct 2023 11:31:28 +0300 Subject: [PATCH 2/3] Apply color config on-the-fly --- app/build.gradle | 2 +- .../kotatsu/core/prefs/AppSettings.kt | 2 +- .../reader/ui/config/ReaderSettings.kt | 22 +++++++++++-------- .../reader/ui/pager/standard/PageHolder.kt | 4 +--- .../reader/ui/pager/webtoon/WebtoonHolder.kt | 7 ++++-- 5 files changed, 21 insertions(+), 16 deletions(-) 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 e0ee582b5..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,7 +336,7 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { return policy.isNetworkAllowed(connectivityManager) } - val enhancedColors: Boolean + val is32BitColorsEnabled: Boolean get() = prefs.getBoolean(KEY_32BIT_COLOR, false) fun isTipEnabled(tip: String): Boolean { 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 cd2189de6..e9b4a6e81 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 @@ -5,7 +5,8 @@ import android.graphics.Bitmap import android.view.View import androidx.lifecycle.MediatorLiveData import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView -import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView.Companion.preferredBitmapConfig +import com.davemorrissey.labs.subscaleview.decoder.SkiaImageDecoder +import com.davemorrissey.labs.subscaleview.decoder.SkiaImageRegionDecoder import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -32,8 +33,12 @@ class ReaderSettings( val colorFilter: ReaderColorFilter? get() = colorFilterFlow.value?.takeUnless { it.isEmpty } - val enhancedColors: Boolean - get() = settings.enhancedColors + val bitmapConfig: Bitmap.Config + get() = if (settings.is32BitColorsEnabled) { + Bitmap.Config.ARGB_8888 + } else { + Bitmap.Config.RGB_565 + } val isPagesNumbersEnabled: Boolean get() = settings.isPagesNumbersEnabled @@ -46,12 +51,11 @@ class ReaderSettings( view.background = bg.resolve(view.context) } - fun enhancedColorsMode() { - val modeEnabled = settings.enhancedColors - preferredBitmapConfig = if (modeEnabled) { - Bitmap.Config.ARGB_8888 - } else { - Bitmap.Config.RGB_565 + fun applyBitmapConfig(ssiv: SubsamplingScaleImageView) { + val config = bitmapConfig + if (ssiv.regionDecoderFactory.bitmapConfig != config) { + ssiv.regionDecoderFactory = SkiaImageRegionDecoder.Factory(config) + ssiv.bitmapDecoderFactory = SkiaImageDecoder.Factory(config) } } 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 39fbc9c77..5fca3d011 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 @@ -4,12 +4,10 @@ import android.annotation.SuppressLint import android.graphics.PointF import android.net.Uri import android.view.View -import androidx.core.view.drawToBitmap 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.SubsamplingScaleImageView.Companion.preferredBitmapConfig import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.model.ZoomMode @@ -48,6 +46,7 @@ open class PageHolder( override fun onConfigChanged() { super.onConfigChanged() binding.zoomControl.isVisible = settings.isZoomControlsEnabled + settings.applyBitmapConfig(binding.ssiv) } @SuppressLint("SetTextI18n") @@ -86,7 +85,6 @@ open class PageHolder( binding.ssiv.height / binding.ssiv.sHeight.toFloat(), ) binding.ssiv.colorFilter = settings.colorFilter?.toColorFilter() - settings.enhancedColorsMode() when (settings.zoomMode) { ZoomMode.FIT_CENTER -> { binding.ssiv.minimumScaleType = SubsamplingScaleImageView.SCALE_TYPE_CENTER_INSIDE 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..6765ed66a 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,16 @@ 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() + settings.applyBitmapConfig(binding.ssiv) + } + override fun onBind(data: ReaderPage) { delegate.onBind(data.toMangaPage()) } From b313c64648a45c1f8764be2b59f06d4b06dd2cd3 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Thu, 12 Oct 2023 12:12:58 +0300 Subject: [PATCH 3/3] Apply color config on-the-fly --- .../kotatsu/reader/ui/config/ReaderSettings.kt | 17 ++++++++++++++--- .../reader/ui/pager/PageHolderDelegate.kt | 8 ++++++++ .../reader/ui/pager/standard/PageHolder.kt | 5 ++++- .../reader/ui/pager/webtoon/WebtoonHolder.kt | 5 ++++- 4 files changed, 30 insertions(+), 5 deletions(-) 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 e9b4a6e81..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 @@ -3,10 +3,12 @@ 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 @@ -16,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( @@ -51,11 +54,19 @@ class ReaderSettings( view.background = bg.resolve(view.context) } - fun applyBitmapConfig(ssiv: SubsamplingScaleImageView) { + @CheckResult + fun applyBitmapConfig(ssiv: SubsamplingScaleImageView): Boolean { val config = bitmapConfig - if (ssiv.regionDecoderFactory.bitmapConfig != config) { - ssiv.regionDecoderFactory = SkiaImageRegionDecoder.Factory(config) + 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 } } 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 5fca3d011..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,7 +46,10 @@ open class PageHolder( override fun onConfigChanged() { super.onConfigChanged() binding.zoomControl.isVisible = settings.isZoomControlsEnabled - settings.applyBitmapConfig(binding.ssiv) + @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 6765ed66a..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 @@ -40,7 +40,10 @@ class WebtoonHolder( override fun onConfigChanged() { super.onConfigChanged() - settings.applyBitmapConfig(binding.ssiv) + @Suppress("SENSELESS_COMPARISON") + if (settings.applyBitmapConfig(binding.ssiv) && delegate != null) { + delegate.reload() + } } override fun onBind(data: ReaderPage) {