Copy smart background from J2k
This commit is contained in:
parent
c340884adb
commit
c2adf2fe0a
@ -901,10 +901,12 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
|
|||||||
}
|
}
|
||||||
.launchIn(scope)
|
.launchIn(scope)
|
||||||
|
|
||||||
preferences.readerTheme().asFlow()
|
// SY -->
|
||||||
|
/*preferences.readerTheme().asFlow()
|
||||||
.drop(1) // We only care about updates
|
.drop(1) // We only care about updates
|
||||||
.onEach { recreate() }
|
.onEach { recreate() }
|
||||||
.launchIn(scope)
|
.launchIn(scope)*/
|
||||||
|
// SY <--
|
||||||
|
|
||||||
preferences.showPageNumber().asFlow()
|
preferences.showPageNumber().asFlow()
|
||||||
.onEach { setPageNumberVisibility(it) }
|
.onEach { setPageNumberVisibility(it) }
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package eu.kanade.tachiyomi.ui.reader.loader
|
package eu.kanade.tachiyomi.ui.reader.loader
|
||||||
|
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||||
|
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerPageHolder
|
||||||
import eu.kanade.tachiyomi.util.lang.plusAssign
|
import eu.kanade.tachiyomi.util.lang.plusAssign
|
||||||
|
import eu.kanade.tachiyomi.util.system.ImageUtil
|
||||||
import exh.EH_SOURCE_ID
|
import exh.EH_SOURCE_ID
|
||||||
import exh.EXH_SOURCE_ID
|
import exh.EXH_SOURCE_ID
|
||||||
import java.util.concurrent.PriorityBlockingQueue
|
import java.util.concurrent.PriorityBlockingQueue
|
||||||
@ -258,6 +261,18 @@ class HttpPageLoader(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.doOnNext {
|
.doOnNext {
|
||||||
|
// SY -->
|
||||||
|
val readerTheme = prefs.readerTheme().get()
|
||||||
|
if (readerTheme >= 3) {
|
||||||
|
val stream = chapterCache.getImageFile(imageUrl).inputStream()
|
||||||
|
val image = BitmapFactory.decodeStream(stream)
|
||||||
|
page.bg = ImageUtil.autoSetBackground(
|
||||||
|
image, readerTheme == 2, prefs.context
|
||||||
|
)
|
||||||
|
page.bgType = PagerPageHolder.getBGType(readerTheme, prefs.context)
|
||||||
|
stream.close()
|
||||||
|
}
|
||||||
|
// SY <--
|
||||||
page.stream = { chapterCache.getImageFile(imageUrl).inputStream() }
|
page.stream = { chapterCache.getImageFile(imageUrl).inputStream() }
|
||||||
page.status = Page.READY
|
page.status = Page.READY
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package eu.kanade.tachiyomi.ui.reader.model
|
package eu.kanade.tachiyomi.ui.reader.model
|
||||||
|
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
@ -7,7 +8,12 @@ class ReaderPage(
|
|||||||
index: Int,
|
index: Int,
|
||||||
url: String = "",
|
url: String = "",
|
||||||
imageUrl: String? = null,
|
imageUrl: String? = null,
|
||||||
|
// SY -->
|
||||||
|
var bg: Drawable? = null,
|
||||||
|
var bgType: Int? = null,
|
||||||
|
// SY <--
|
||||||
var stream: (() -> InputStream)? = null
|
var stream: (() -> InputStream)? = null
|
||||||
|
|
||||||
) : Page(index, url, imageUrl, null) {
|
) : Page(index, url, imageUrl, null) {
|
||||||
|
|
||||||
lateinit var chapter: ReaderChapter
|
lateinit var chapter: ReaderChapter
|
||||||
|
@ -20,6 +20,11 @@ class PagerConfig(private val viewer: PagerViewer, preferences: PreferencesHelpe
|
|||||||
var imageCropBorders = false
|
var imageCropBorders = false
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
// SY -->
|
||||||
|
var readerTheme = 0
|
||||||
|
private set
|
||||||
|
// SY <--
|
||||||
|
|
||||||
init {
|
init {
|
||||||
preferences.imageScaleType()
|
preferences.imageScaleType()
|
||||||
.register({ imageScaleType = it }, { imagePropertyChangedListener?.invoke() })
|
.register({ imageScaleType = it }, { imagePropertyChangedListener?.invoke() })
|
||||||
@ -29,6 +34,11 @@ class PagerConfig(private val viewer: PagerViewer, preferences: PreferencesHelpe
|
|||||||
|
|
||||||
preferences.cropBorders()
|
preferences.cropBorders()
|
||||||
.register({ imageCropBorders = it }, { imagePropertyChangedListener?.invoke() })
|
.register({ imageCropBorders = it }, { imagePropertyChangedListener?.invoke() })
|
||||||
|
|
||||||
|
// SY -->
|
||||||
|
preferences.readerTheme()
|
||||||
|
.register({ readerTheme = it }, { imagePropertyChangedListener?.invoke() })
|
||||||
|
// SY <--
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun zoomTypeFromPreference(value: Int) {
|
private fun zoomTypeFromPreference(value: Int) {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package eu.kanade.tachiyomi.ui.reader.viewer.pager
|
package eu.kanade.tachiyomi.ui.reader.viewer.pager
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
import android.graphics.PointF
|
import android.graphics.PointF
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.view.GestureDetector
|
import android.view.GestureDetector
|
||||||
@ -27,20 +29,26 @@ import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
|||||||
import com.github.chrisbanes.photoview.PhotoView
|
import com.github.chrisbanes.photoview.PhotoView
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.glide.GlideApp
|
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressBar
|
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressBar
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerConfig.ZoomType
|
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerConfig.ZoomType
|
||||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
||||||
|
import eu.kanade.tachiyomi.util.lang.launchUI
|
||||||
import eu.kanade.tachiyomi.util.system.ImageUtil
|
import eu.kanade.tachiyomi.util.system.ImageUtil
|
||||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||||
import eu.kanade.tachiyomi.widget.ViewPagerAdapter
|
import eu.kanade.tachiyomi.widget.ViewPagerAdapter
|
||||||
|
import exh.util.isInNightMode
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.Subscription
|
import rx.Subscription
|
||||||
import rx.android.schedulers.AndroidSchedulers
|
import rx.android.schedulers.AndroidSchedulers
|
||||||
import rx.schedulers.Schedulers
|
import rx.schedulers.Schedulers
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View of the ViewPager that contains a page of a chapter.
|
* View of the ViewPager that contains a page of a chapter.
|
||||||
@ -242,7 +250,34 @@ class PagerPageHolder(
|
|||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.doOnNext { isAnimated ->
|
.doOnNext { isAnimated ->
|
||||||
if (!isAnimated) {
|
if (!isAnimated) {
|
||||||
initSubsamplingImageView().setImage(ImageSource.inputStream(openStream!!))
|
// SY -->
|
||||||
|
if (viewer.config.readerTheme >= 3) {
|
||||||
|
val imageView = initSubsamplingImageView()
|
||||||
|
if (page.bg != null && page.bgType == getBGType(
|
||||||
|
viewer.config.readerTheme,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
imageView.setImage(ImageSource.inputStream(openStream!!))
|
||||||
|
imageView.background = page.bg
|
||||||
|
}
|
||||||
|
// if the user switches to automatic when pages are already cached, the bg needs to be loaded
|
||||||
|
else {
|
||||||
|
val bytesArray = openStream!!.readBytes()
|
||||||
|
val bytesStream = bytesArray.inputStream()
|
||||||
|
imageView.setImage(ImageSource.inputStream(bytesStream))
|
||||||
|
bytesStream.close()
|
||||||
|
|
||||||
|
launchUI {
|
||||||
|
imageView.background = setBG(bytesArray)
|
||||||
|
page.bg = imageView.background
|
||||||
|
page.bgType = getBGType(viewer.config.readerTheme, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
initSubsamplingImageView().setImage(ImageSource.inputStream(openStream!!))
|
||||||
|
}
|
||||||
|
// SY <--
|
||||||
} else {
|
} else {
|
||||||
initImageView().setImage(openStream!!)
|
initImageView().setImage(openStream!!)
|
||||||
}
|
}
|
||||||
@ -253,6 +288,20 @@ class PagerPageHolder(
|
|||||||
.subscribe({}, {})
|
.subscribe({}, {})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SY -->
|
||||||
|
private suspend fun setBG(bytesArray: ByteArray): Drawable {
|
||||||
|
return withContext(Dispatchers.Default) {
|
||||||
|
val preferences by injectLazy<PreferencesHelper>()
|
||||||
|
ImageUtil.autoSetBackground(
|
||||||
|
BitmapFactory.decodeByteArray(
|
||||||
|
bytesArray, 0, bytesArray.size
|
||||||
|
),
|
||||||
|
preferences.readerTheme().get() == 3, context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// SY <--
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the page has an error.
|
* Called when the page has an error.
|
||||||
*/
|
*/
|
||||||
@ -464,4 +513,14 @@ class PagerPageHolder(
|
|||||||
})
|
})
|
||||||
.into(this)
|
.into(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SY -->
|
||||||
|
companion object {
|
||||||
|
fun getBGType(readerTheme: Int, context: Context): Int {
|
||||||
|
return if (readerTheme == 3) {
|
||||||
|
if (context.isInNightMode()) 2 else 1
|
||||||
|
} else 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// SY <--
|
||||||
}
|
}
|
||||||
|
@ -78,8 +78,8 @@ class SettingsReaderController : SettingsController() {
|
|||||||
intListPreference {
|
intListPreference {
|
||||||
key = Keys.readerTheme
|
key = Keys.readerTheme
|
||||||
titleRes = R.string.pref_reader_theme
|
titleRes = R.string.pref_reader_theme
|
||||||
entriesRes = arrayOf(R.string.black_background, R.string.gray_background, R.string.white_background)
|
entriesRes = arrayOf(R.string.black_background, R.string.gray_background, R.string.white_background, R.string.smart_based_on_page, R.string.smart_based_on_page_and_theme)
|
||||||
entryValues = arrayOf("1", "2", "0")
|
entryValues = arrayOf("1", "2", "0", "3", "4")
|
||||||
defaultValue = "1"
|
defaultValue = "1"
|
||||||
summary = "%s"
|
summary = "%s"
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,15 @@
|
|||||||
package eu.kanade.tachiyomi.util.system
|
package eu.kanade.tachiyomi.util.system
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.drawable.ColorDrawable
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.graphics.drawable.GradientDrawable
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.net.URLConnection
|
import java.net.URLConnection
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
object ImageUtil {
|
object ImageUtil {
|
||||||
|
|
||||||
@ -71,4 +79,205 @@ object ImageUtil {
|
|||||||
GIF("image/gif", "gif"),
|
GIF("image/gif", "gif"),
|
||||||
WEBP("image/webp", "webp")
|
WEBP("image/webp", "webp")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SY -->
|
||||||
|
fun autoSetBackground(image: Bitmap?, alwaysUseWhite: Boolean, context: Context): Drawable {
|
||||||
|
val backgroundColor = if (alwaysUseWhite) Color.WHITE else {
|
||||||
|
context.getResourceColor(R.attr.colorPrimary)
|
||||||
|
}
|
||||||
|
if (image == null) return ColorDrawable(backgroundColor)
|
||||||
|
if (image.width < 50 || image.height < 50) {
|
||||||
|
return ColorDrawable(backgroundColor)
|
||||||
|
}
|
||||||
|
val top = 5
|
||||||
|
val bot = image.height - 5
|
||||||
|
val left = (image.width * 0.0275).toInt()
|
||||||
|
val right = image.width - left
|
||||||
|
val midX = image.width / 2
|
||||||
|
val midY = image.height / 2
|
||||||
|
val offsetX = (image.width * 0.01).toInt()
|
||||||
|
val offsetY = (image.height * 0.01).toInt()
|
||||||
|
val topLeftIsDark = isDark(image.getPixel(left, top))
|
||||||
|
val topRightIsDark = isDark(image.getPixel(right, top))
|
||||||
|
val midLeftIsDark = isDark(image.getPixel(left, midY))
|
||||||
|
val midRightIsDark = isDark(image.getPixel(right, midY))
|
||||||
|
val topMidIsDark = isDark(image.getPixel(midX, top))
|
||||||
|
val botLeftIsDark = isDark(image.getPixel(left, bot))
|
||||||
|
val botRightIsDark = isDark(image.getPixel(right, bot))
|
||||||
|
|
||||||
|
var darkBG = (topLeftIsDark && (botLeftIsDark || botRightIsDark || topRightIsDark || midLeftIsDark || topMidIsDark)) ||
|
||||||
|
(topRightIsDark && (botRightIsDark || botLeftIsDark || midRightIsDark || topMidIsDark))
|
||||||
|
|
||||||
|
if (!isWhite(image.getPixel(left, top)) && pixelIsClose(image.getPixel(left, top), image.getPixel(midX, top)) &&
|
||||||
|
!isWhite(image.getPixel(midX, top)) && pixelIsClose(image.getPixel(midX, top), image.getPixel(right, top)) &&
|
||||||
|
!isWhite(image.getPixel(right, top)) && pixelIsClose(image.getPixel(right, top), image.getPixel(right, bot)) &&
|
||||||
|
!isWhite(image.getPixel(right, bot)) && pixelIsClose(image.getPixel(right, bot), image.getPixel(midX, bot)) &&
|
||||||
|
!isWhite(image.getPixel(midX, bot)) && pixelIsClose(image.getPixel(midX, bot), image.getPixel(left, bot)) &&
|
||||||
|
!isWhite(image.getPixel(left, bot)) && pixelIsClose(image.getPixel(left, bot), image.getPixel(left, top))
|
||||||
|
) {
|
||||||
|
return ColorDrawable(image.getPixel(left, top))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isWhite(image.getPixel(left, top)).toInt() +
|
||||||
|
isWhite(image.getPixel(right, top)).toInt() +
|
||||||
|
isWhite(image.getPixel(left, bot)).toInt() +
|
||||||
|
isWhite(image.getPixel(right, bot)).toInt() > 2
|
||||||
|
) {
|
||||||
|
darkBG = false
|
||||||
|
}
|
||||||
|
|
||||||
|
var blackPixel = when {
|
||||||
|
topLeftIsDark -> image.getPixel(left, top)
|
||||||
|
topRightIsDark -> image.getPixel(right, top)
|
||||||
|
botLeftIsDark -> image.getPixel(left, bot)
|
||||||
|
botRightIsDark -> image.getPixel(right, bot)
|
||||||
|
else -> backgroundColor
|
||||||
|
}
|
||||||
|
|
||||||
|
var overallWhitePixels = 0
|
||||||
|
var overallBlackPixels = 0
|
||||||
|
var topBlackStreak = 0
|
||||||
|
var topWhiteStreak = 0
|
||||||
|
var botBlackStreak = 0
|
||||||
|
var botWhiteStreak = 0
|
||||||
|
outer@ for (x in intArrayOf(left, right, left - offsetX, right + offsetX)) {
|
||||||
|
var whitePixelsStreak = 0
|
||||||
|
var whitePixels = 0
|
||||||
|
var blackPixelsStreak = 0
|
||||||
|
var blackPixels = 0
|
||||||
|
var blackStreak = false
|
||||||
|
var whiteStrak = false
|
||||||
|
val notOffset = x == left || x == right
|
||||||
|
for ((index, y) in (0 until image.height step image.height / 25).withIndex()) {
|
||||||
|
val pixel = image.getPixel(x, y)
|
||||||
|
val pixelOff = image.getPixel(x + (if (x < image.width / 2) -offsetX else offsetX), y)
|
||||||
|
if (isWhite(pixel)) {
|
||||||
|
whitePixelsStreak++
|
||||||
|
whitePixels++
|
||||||
|
if (notOffset) {
|
||||||
|
overallWhitePixels++
|
||||||
|
}
|
||||||
|
if (whitePixelsStreak > 14) {
|
||||||
|
whiteStrak = true
|
||||||
|
}
|
||||||
|
if (whitePixelsStreak > 6 && whitePixelsStreak >= index - 1) {
|
||||||
|
topWhiteStreak = whitePixelsStreak
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
whitePixelsStreak = 0
|
||||||
|
if (isDark(pixel) && isDark(pixelOff)) {
|
||||||
|
blackPixels++
|
||||||
|
if (notOffset) {
|
||||||
|
overallBlackPixels++
|
||||||
|
}
|
||||||
|
blackPixelsStreak++
|
||||||
|
if (blackPixelsStreak >= 14) {
|
||||||
|
blackStreak = true
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (blackPixelsStreak > 6 && blackPixelsStreak >= index - 1) {
|
||||||
|
topBlackStreak = blackPixelsStreak
|
||||||
|
}
|
||||||
|
blackPixelsStreak = 0
|
||||||
|
}
|
||||||
|
if (blackPixelsStreak > 6) {
|
||||||
|
botBlackStreak = blackPixelsStreak
|
||||||
|
} else if (whitePixelsStreak > 6) {
|
||||||
|
botWhiteStreak = whitePixelsStreak
|
||||||
|
}
|
||||||
|
when {
|
||||||
|
blackPixels > 22 -> {
|
||||||
|
if (x == right || x == right + offsetX) {
|
||||||
|
blackPixel = when {
|
||||||
|
topRightIsDark -> image.getPixel(right, top)
|
||||||
|
botRightIsDark -> image.getPixel(right, bot)
|
||||||
|
else -> blackPixel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
darkBG = true
|
||||||
|
overallWhitePixels = 0
|
||||||
|
break@outer
|
||||||
|
}
|
||||||
|
blackStreak -> {
|
||||||
|
darkBG = true
|
||||||
|
if (x == right || x == right + offsetX) {
|
||||||
|
blackPixel = when {
|
||||||
|
topRightIsDark -> image.getPixel(right, top)
|
||||||
|
botRightIsDark -> image.getPixel(right, bot)
|
||||||
|
else -> blackPixel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (blackPixels > 18) {
|
||||||
|
overallWhitePixels = 0
|
||||||
|
break@outer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
whiteStrak || whitePixels > 22 -> darkBG = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val topIsBlackStreak = topBlackStreak > topWhiteStreak
|
||||||
|
val bottomIsBlackStreak = botBlackStreak > botWhiteStreak
|
||||||
|
if (overallWhitePixels > 9 && overallWhitePixels > overallBlackPixels) {
|
||||||
|
darkBG = false
|
||||||
|
}
|
||||||
|
if (topIsBlackStreak && bottomIsBlackStreak) {
|
||||||
|
darkBG = true
|
||||||
|
}
|
||||||
|
if (darkBG) {
|
||||||
|
return if (isWhite(image.getPixel(left, bot)) && isWhite(image.getPixel(right, bot))) {
|
||||||
|
GradientDrawable(
|
||||||
|
GradientDrawable.Orientation.TOP_BOTTOM,
|
||||||
|
intArrayOf(blackPixel, blackPixel, backgroundColor, backgroundColor)
|
||||||
|
)
|
||||||
|
} else if (isWhite(image.getPixel(left, top)) && isWhite(image.getPixel(right, top))) {
|
||||||
|
GradientDrawable(
|
||||||
|
GradientDrawable.Orientation.TOP_BOTTOM,
|
||||||
|
intArrayOf(backgroundColor, backgroundColor, blackPixel, blackPixel)
|
||||||
|
)
|
||||||
|
} else ColorDrawable(blackPixel)
|
||||||
|
}
|
||||||
|
if (topIsBlackStreak || (
|
||||||
|
topLeftIsDark && topRightIsDark &&
|
||||||
|
isDark(image.getPixel(left - offsetX, top)) && isDark(image.getPixel(right + offsetX, top)) &&
|
||||||
|
(topMidIsDark || overallBlackPixels > 9)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return GradientDrawable(
|
||||||
|
GradientDrawable.Orientation.TOP_BOTTOM,
|
||||||
|
intArrayOf(blackPixel, blackPixel, backgroundColor, backgroundColor)
|
||||||
|
)
|
||||||
|
} else if (bottomIsBlackStreak || (
|
||||||
|
botLeftIsDark && botRightIsDark &&
|
||||||
|
isDark(image.getPixel(left - offsetX, bot)) && isDark(image.getPixel(right + offsetX, bot)) &&
|
||||||
|
(isDark(image.getPixel(midX, bot)) || overallBlackPixels > 9)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return GradientDrawable(
|
||||||
|
GradientDrawable.Orientation.TOP_BOTTOM,
|
||||||
|
intArrayOf(backgroundColor, backgroundColor, blackPixel, blackPixel)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return ColorDrawable(backgroundColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isDark(color: Int): Boolean {
|
||||||
|
return Color.red(color) < 40 && Color.blue(color) < 40 && Color.green(color) < 40 &&
|
||||||
|
Color.alpha(color) > 200
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isWhite(color: Int): Boolean {
|
||||||
|
return Color.red(color) + Color.blue(color) + Color.green(color) > 740
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Boolean.toInt() = if (this) 1 else 0
|
||||||
|
|
||||||
|
private fun pixelIsClose(color1: Int, color2: Int): Boolean {
|
||||||
|
return abs(Color.red(color1) - Color.red(color2)) < 30 &&
|
||||||
|
abs(Color.green(color1) - Color.green(color2)) < 30 &&
|
||||||
|
abs(Color.blue(color1) - Color.blue(color2)) < 30
|
||||||
|
}
|
||||||
|
// SY <--
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package exh.util
|
|||||||
import android.app.job.JobScheduler
|
import android.app.job.JobScheduler
|
||||||
import android.content.ClipboardManager
|
import android.content.ClipboardManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.res.Configuration
|
||||||
import android.net.wifi.WifiManager
|
import android.net.wifi.WifiManager
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -16,3 +17,8 @@ val Context.clipboardManager: ClipboardManager
|
|||||||
|
|
||||||
val Context.jobScheduler: JobScheduler
|
val Context.jobScheduler: JobScheduler
|
||||||
get() = applicationContext.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
|
get() = applicationContext.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
|
||||||
|
|
||||||
|
fun Context.isInNightMode(): Boolean {
|
||||||
|
val currentNightMode = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
|
||||||
|
return currentNightMode == Configuration.UI_MODE_NIGHT_YES
|
||||||
|
}
|
||||||
|
@ -13,12 +13,16 @@
|
|||||||
<item>@string/black_background</item>
|
<item>@string/black_background</item>
|
||||||
<item>@string/gray_background</item>
|
<item>@string/gray_background</item>
|
||||||
<item>@string/white_background</item>
|
<item>@string/white_background</item>
|
||||||
|
<item>@string/smart_based_on_page</item>
|
||||||
|
<item>@string/smart_based_on_page_and_theme</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="reader_themes_values">
|
<string-array name="reader_themes_values">
|
||||||
<item>1</item>
|
<item>1</item>
|
||||||
<item>2</item>
|
<item>2</item>
|
||||||
<item>0</item>
|
<item>0</item>
|
||||||
|
<item>3</item>
|
||||||
|
<item>4</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="image_scale_type">
|
<string-array name="image_scale_type">
|
||||||
|
@ -187,6 +187,8 @@
|
|||||||
<string name="auto_webtoon_mode">Auto Webtoon Mode</string>
|
<string name="auto_webtoon_mode">Auto Webtoon Mode</string>
|
||||||
<string name="auto_webtoon_mode_summary">Use auto webtoon mode for manga that are detected to likely use the long strip format</string>
|
<string name="auto_webtoon_mode_summary">Use auto webtoon mode for manga that are detected to likely use the long strip format</string>
|
||||||
<string name="enable_zoom_out">Enable zoom out</string>
|
<string name="enable_zoom_out">Enable zoom out</string>
|
||||||
|
<string name="smart_based_on_page">Smart (based on page)</string>
|
||||||
|
<string name="smart_based_on_page_and_theme">Smart (based on page and theme)</string>
|
||||||
|
|
||||||
<!-- Reader -->
|
<!-- Reader -->
|
||||||
<!-- Reader Actions -->
|
<!-- Reader Actions -->
|
||||||
|
Loading…
x
Reference in New Issue
Block a user