PagerPageHolder: Move chooseBackground call to IO thread (#5737)

* ImageUtil.chooseBackground: Use built-in decoder

* PagerPageHolder: Move chooseBackground call to IO thread

Also move stuffs and reuse image stream as bytes
This commit is contained in:
Ivan Iskandar 2021-08-19 20:15:45 +07:00 committed by GitHub
parent da16110e1c
commit 11a8046c5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 21 deletions

View File

@ -37,6 +37,7 @@ 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 java.io.ByteArrayInputStream
import java.io.InputStream import java.io.InputStream
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -258,31 +259,40 @@ class PagerPageHolder(
unsubscribeReadImageHeader() unsubscribeReadImageHeader()
val streamFn = page.stream ?: return val streamFn = page.stream ?: return
var openStream: InputStream? = null
readImageHeaderSubscription = Observable readImageHeaderSubscription = Observable
.fromCallable { .fromCallable {
val stream = streamFn().buffered(16) val stream = streamFn().buffered(16)
openStream = process(item, stream) val itemStream = process(item, stream)
try {
ImageUtil.isAnimatedAndSupported(stream) val streamBytes = itemStream.readBytes()
val isAnimated = ImageUtil.isAnimatedAndSupported(stream)
val background = if (!isAnimated && viewer.config.automaticBackground) {
ByteArrayInputStream(streamBytes).use { bais ->
ImageUtil.chooseBackground(context, bais)
}
} else {
null
}
Triple(streamBytes, isAnimated, background)
} finally {
stream.close()
itemStream.close()
}
} }
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.doOnNext { isAnimated -> .doOnNext { (streamBytes, isAnimated, background) ->
ByteArrayInputStream(streamBytes).use { bais ->
if (!isAnimated) { if (!isAnimated) {
this.background = background
initSubsamplingImageView().apply { initSubsamplingImageView().apply {
if (viewer.config.automaticBackground) { setImage(ImageSource.inputStream(bais))
background = ImageUtil.chooseBackground(context, openStream!!)
}
setImage(ImageSource.inputStream(openStream!!))
} }
} else { } else {
initImageView().setImage(openStream!!) initImageView().setImage(bais)
}
} }
} }
// Keep the Rx stream alive to close the input stream only when unsubscribed
.flatMap { Observable.never<Unit>() }
.doOnUnsubscribe { openStream?.close() }
.subscribe({}, {}) .subscribe({}, {})
} }

View File

@ -18,7 +18,6 @@ import androidx.core.graphics.green
import androidx.core.graphics.red import androidx.core.graphics.red
import tachiyomi.decoder.Format import tachiyomi.decoder.Format
import tachiyomi.decoder.ImageDecoder import tachiyomi.decoder.ImageDecoder
import tachiyomi.decoder.ImageType
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.io.InputStream import java.io.InputStream
@ -181,11 +180,9 @@ object ImageUtil {
* Algorithm for determining what background to accompany a comic/manga page * Algorithm for determining what background to accompany a comic/manga page
*/ */
fun chooseBackground(context: Context, imageStream: InputStream): Drawable { fun chooseBackground(context: Context, imageStream: InputStream): Drawable {
imageStream.mark(imageStream.available() + 1) val decoder = ImageDecoder.newInstance(imageStream)
val image = decoder?.decode()
val image = BitmapFactory.decodeStream(imageStream) decoder?.recycle()
imageStream.reset()
val whiteColor = Color.WHITE val whiteColor = Color.WHITE
if (image == null) return ColorDrawable(whiteColor) if (image == null) return ColorDrawable(whiteColor)