Cleanup dual page split (#4956)

* Cleanup Dual Page Split

* Move where images is processed

* Change parameter name to imageStream

* Use available instead of Int.MAX_VALUE

* Update JavaDoc
This commit is contained in:
Andreas 2021-04-25 17:08:51 +02:00 committed by GitHub
parent f608cb55eb
commit 662b71436e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 32 deletions

View file

@ -235,16 +235,13 @@ class PagerPageHolder(
readImageHeaderSubscription = Observable readImageHeaderSubscription = Observable
.fromCallable { .fromCallable {
val stream = streamFn().buffered(16) val stream = streamFn().buffered(16)
openStream = stream openStream = process(stream)
ImageUtil.findImageType(stream) == ImageUtil.ImageType.GIF ImageUtil.findImageType(stream) == ImageUtil.ImageType.GIF
} }
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.doOnNext { isAnimated -> .doOnNext { isAnimated ->
if (viewer.config.dualPageSplit) {
openStream = processDualPageSplit(openStream!!)
}
if (!isAnimated) { if (!isAnimated) {
initSubsamplingImageView().setImage(ImageSource.inputStream(openStream!!)) initSubsamplingImageView().setImage(ImageSource.inputStream(openStream!!))
} else { } else {
@ -257,21 +254,31 @@ class PagerPageHolder(
.subscribe({}, {}) .subscribe({}, {})
} }
private fun processDualPageSplit(openStream: InputStream): InputStream { private fun process(imageStream: InputStream): InputStream {
var inputStream = openStream if (!viewer.config.dualPageSplit) {
val (isDoublePage, stream) = when (page) { return imageStream
is InsertPage -> Pair(true, inputStream)
else -> ImageUtil.isDoublePage(inputStream)
} }
inputStream = stream
if (!isDoublePage) return inputStream if (page is InsertPage) {
return splitInHalf(imageStream)
}
val isDoublePage = ImageUtil.isDoublePage(imageStream)
if (!isDoublePage) {
return imageStream
}
onPageSplit()
return splitInHalf(imageStream)
}
private fun splitInHalf(imageStream: InputStream): InputStream {
var side = when { var side = when {
viewer is L2RPagerViewer && page is InsertPage -> ImageUtil.Side.RIGHT viewer is L2RPagerViewer && page is InsertPage -> ImageUtil.Side.RIGHT
(viewer is R2LPagerViewer || viewer is VerticalPagerViewer) && page is InsertPage -> ImageUtil.Side.LEFT viewer !is L2RPagerViewer && page is InsertPage -> ImageUtil.Side.LEFT
viewer is L2RPagerViewer && page !is InsertPage -> ImageUtil.Side.LEFT viewer is L2RPagerViewer && page !is InsertPage -> ImageUtil.Side.LEFT
(viewer is R2LPagerViewer || viewer is VerticalPagerViewer) && page !is InsertPage -> ImageUtil.Side.RIGHT viewer !is L2RPagerViewer && page !is InsertPage -> ImageUtil.Side.RIGHT
else -> error("We should choose a side!") else -> error("We should choose a side!")
} }
@ -282,11 +289,7 @@ class PagerPageHolder(
} }
} }
if (page !is InsertPage) { return ImageUtil.splitInHalf(imageStream, side)
onPageSplit()
}
return ImageUtil.splitInHalf(inputStream, side)
} }
private fun onPageSplit() { private fun onPageSplit() {

View file

@ -385,8 +385,11 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
} }
fun onPageSplit(currentPage: ReaderPage, newPage: InsertPage) { fun onPageSplit(currentPage: ReaderPage, newPage: InsertPage) {
activity.runOnUiThread {
// Need to insert on UI thread else images will go blank
adapter.onPageSplit(currentPage, newPage, this::class.java) adapter.onPageSplit(currentPage, newPage, this::class.java)
} }
}
private fun cleanupPageSplit() { private fun cleanupPageSplit() {
adapter.cleanupPageSplit() adapter.cleanupPageSplit()

View file

@ -281,22 +281,13 @@ class WebtoonPageHolder(
readImageHeaderSubscription = Observable readImageHeaderSubscription = Observable
.fromCallable { .fromCallable {
val stream = streamFn().buffered(16) val stream = streamFn().buffered(16)
openStream = stream openStream = process(stream)
ImageUtil.findImageType(stream) == ImageUtil.ImageType.GIF ImageUtil.findImageType(stream) == ImageUtil.ImageType.GIF
} }
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.doOnNext { isAnimated -> .doOnNext { isAnimated ->
if (viewer.config.dualPageSplit) {
val (isDoublePage, stream) = ImageUtil.isDoublePage(openStream!!)
openStream = if (!isDoublePage) {
stream
} else {
val upperSide = if (viewer.config.dualPageInvert) ImageUtil.Side.LEFT else ImageUtil.Side.RIGHT
ImageUtil.splitAndMerge(stream, upperSide)
}
}
if (!isAnimated) { if (!isAnimated) {
val subsamplingView = initSubsamplingImageView() val subsamplingView = initSubsamplingImageView()
subsamplingView.isVisible = true subsamplingView.isVisible = true
@ -315,6 +306,20 @@ class WebtoonPageHolder(
addSubscription(readImageHeaderSubscription) addSubscription(readImageHeaderSubscription)
} }
private fun process(imageStream: InputStream): InputStream {
if (!viewer.config.dualPageSplit) {
return imageStream
}
val isDoublePage = ImageUtil.isDoublePage(imageStream)
if (!isDoublePage) {
return imageStream
}
val upperSide = if (viewer.config.dualPageInvert) ImageUtil.Side.LEFT else ImageUtil.Side.RIGHT
return ImageUtil.splitAndMerge(imageStream, upperSide)
}
/** /**
* Called when the page has an error. * Called when the page has an error.
*/ */

View file

@ -77,15 +77,20 @@ object ImageUtil {
} }
/** /**
* Check whether the image is a double image (width > height), return the result and original stream * Check whether the image is a double-page spread
* @return true if the width is greater than the height
*/ */
fun isDoublePage(imageStream: InputStream): Pair<Boolean, InputStream> { fun isDoublePage(imageStream: InputStream): Boolean {
imageStream.mark(imageStream.available() + 1)
val imageBytes = imageStream.readBytes() val imageBytes = imageStream.readBytes()
val options = BitmapFactory.Options().apply { inJustDecodeBounds = true } val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size, options) BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size, options)
return Pair(options.outWidth > options.outHeight, ByteArrayInputStream(imageBytes)) imageStream.reset()
return options.outWidth > options.outHeight
} }
/** /**