From 11a8046c5fa00a6abbaf387ab5c75a9a294a01b8 Mon Sep 17 00:00:00 2001 From: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com> Date: Thu, 19 Aug 2021 20:15:45 +0700 Subject: [PATCH] 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 --- .../ui/reader/viewer/pager/PagerPageHolder.kt | 40 ++++++++++++------- .../kanade/tachiyomi/util/system/ImageUtil.kt | 9 ++--- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt index 45a994ad28..6d3d32e11f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt @@ -37,6 +37,7 @@ import rx.Observable import rx.Subscription import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers +import java.io.ByteArrayInputStream import java.io.InputStream import java.nio.ByteBuffer import java.util.concurrent.TimeUnit @@ -258,31 +259,40 @@ class PagerPageHolder( unsubscribeReadImageHeader() val streamFn = page.stream ?: return - var openStream: InputStream? = null readImageHeaderSubscription = Observable .fromCallable { val stream = streamFn().buffered(16) - openStream = process(item, stream) - - ImageUtil.isAnimatedAndSupported(stream) + val itemStream = process(item, stream) + try { + 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()) .observeOn(AndroidSchedulers.mainThread()) - .doOnNext { isAnimated -> - if (!isAnimated) { - initSubsamplingImageView().apply { - if (viewer.config.automaticBackground) { - background = ImageUtil.chooseBackground(context, openStream!!) + .doOnNext { (streamBytes, isAnimated, background) -> + ByteArrayInputStream(streamBytes).use { bais -> + if (!isAnimated) { + this.background = background + initSubsamplingImageView().apply { + setImage(ImageSource.inputStream(bais)) } - setImage(ImageSource.inputStream(openStream!!)) + } else { + initImageView().setImage(bais) } - } else { - initImageView().setImage(openStream!!) } } - // Keep the Rx stream alive to close the input stream only when unsubscribed - .flatMap { Observable.never() } - .doOnUnsubscribe { openStream?.close() } .subscribe({}, {}) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/ImageUtil.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/ImageUtil.kt index 998d1f71b2..3c4a564540 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/ImageUtil.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/ImageUtil.kt @@ -18,7 +18,6 @@ import androidx.core.graphics.green import androidx.core.graphics.red import tachiyomi.decoder.Format import tachiyomi.decoder.ImageDecoder -import tachiyomi.decoder.ImageType import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.InputStream @@ -181,11 +180,9 @@ object ImageUtil { * Algorithm for determining what background to accompany a comic/manga page */ fun chooseBackground(context: Context, imageStream: InputStream): Drawable { - imageStream.mark(imageStream.available() + 1) - - val image = BitmapFactory.decodeStream(imageStream) - - imageStream.reset() + val decoder = ImageDecoder.newInstance(imageStream) + val image = decoder?.decode() + decoder?.recycle() val whiteColor = Color.WHITE if (image == null) return ColorDrawable(whiteColor)