From 39c0b7425070d2dd86d543eafdfb72e7a94a6a99 Mon Sep 17 00:00:00 2001 From: arkon Date: Fri, 6 May 2022 23:10:56 -0400 Subject: [PATCH] Fix tall image split math issues - Round up per-split height to ensure the entire page ends up being split - Handle the last split of a page potentially being shorter than the others --- .../kanade/tachiyomi/data/download/Downloader.kt | 15 ++++++++++----- .../ui/reader/viewer/pager/PagerPageHolder.kt | 3 ++- .../ui/reader/viewer/webtoon/WebtoonPageHolder.kt | 3 ++- .../eu/kanade/tachiyomi/util/system/ImageUtil.kt | 3 ++- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt index dafce33e7..b4535cfde 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt @@ -46,6 +46,8 @@ import java.io.FileOutputStream import java.util.zip.CRC32 import java.util.zip.ZipEntry import java.util.zip.ZipOutputStream +import kotlin.math.ceil +import kotlin.math.min /** * This class is the one in charge of downloading chapters. @@ -569,25 +571,28 @@ class Downloader( val bitmap = BitmapFactory.decodeFile(imageFile.filePath) val splitsCount = bitmap.height / context.resources.displayMetrics.heightPixels + 1 - val heightPerSplit = bitmap.height / splitsCount + val heightPerSplit = ceil(bitmap.height / splitsCount.toDouble()).toInt() + logcat { "Splitting height ${bitmap.height} by $splitsCount * $heightPerSplit" } try { - (0..splitsCount).forEach { split -> + (0 until splitsCount).forEach { split -> + logcat { "Split #$split at y=${split * heightPerSplit}" } val splitPath = imageFile.filePath!!.substringBeforeLast(".") + "__${"%03d".format(split + 1)}.jpg" + val splitHeight = split * heightPerSplit FileOutputStream(splitPath).use { stream -> Bitmap.createBitmap( bitmap, 0, - split * heightPerSplit, + splitHeight, bitmap.width, - heightPerSplit, + min(heightPerSplit, bitmap.height - splitHeight), ).compress(Bitmap.CompressFormat.JPEG, 100, stream) } } imageFile.delete() } catch (e: Exception) { // Image splits were not successfully saved so delete them and keep the original image - (0..splitsCount) + (0 until splitsCount) .map { imageFile.filePath!!.substringBeforeLast(".") + "__${"%03d".format(it + 1)}.jpg" } .forEach { File(it).delete() } throw e 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 408b0263c..694c47da6 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 @@ -19,6 +19,7 @@ import rx.Observable import rx.Subscription import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers +import java.io.BufferedInputStream import java.io.ByteArrayInputStream import java.io.InputStream import java.util.concurrent.TimeUnit @@ -238,7 +239,7 @@ class PagerPageHolder( .subscribe({}, {}) } - private fun process(page: ReaderPage, imageStream: InputStream): InputStream { + private fun process(page: ReaderPage, imageStream: BufferedInputStream): InputStream { if (!viewer.config.dualPageSplit) { return imageStream } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt index ebeef9ecf..3463eafd6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt @@ -23,6 +23,7 @@ import rx.Observable import rx.Subscription import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers +import java.io.BufferedInputStream import java.io.InputStream import java.util.concurrent.TimeUnit @@ -272,7 +273,7 @@ class WebtoonPageHolder( addSubscription(readImageHeaderSubscription) } - private fun process(imageStream: InputStream): InputStream { + private fun process(imageStream: BufferedInputStream): InputStream { if (!viewer.config.dualPageSplit) { return imageStream } 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 f634dd5d2..a596600aa 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,6 +18,7 @@ import androidx.core.graphics.green import androidx.core.graphics.red import tachiyomi.decoder.Format import tachiyomi.decoder.ImageDecoder +import java.io.BufferedInputStream import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.InputStream @@ -103,7 +104,7 @@ object ImageUtil { * * @return true if the width is greater than the height */ - fun isWideImage(imageStream: InputStream): Boolean { + fun isWideImage(imageStream: BufferedInputStream): Boolean { val options = extractImageOptions(imageStream) imageStream.reset() return options.outWidth > options.outHeight