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
This commit is contained in:
arkon 2022-05-06 23:10:56 -04:00
parent a9e629aea6
commit 39c0b74250
4 changed files with 16 additions and 8 deletions

View File

@ -46,6 +46,8 @@ import java.io.FileOutputStream
import java.util.zip.CRC32 import java.util.zip.CRC32
import java.util.zip.ZipEntry import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream import java.util.zip.ZipOutputStream
import kotlin.math.ceil
import kotlin.math.min
/** /**
* This class is the one in charge of downloading chapters. * This class is the one in charge of downloading chapters.
@ -569,25 +571,28 @@ class Downloader(
val bitmap = BitmapFactory.decodeFile(imageFile.filePath) val bitmap = BitmapFactory.decodeFile(imageFile.filePath)
val splitsCount = bitmap.height / context.resources.displayMetrics.heightPixels + 1 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 { 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 splitPath = imageFile.filePath!!.substringBeforeLast(".") + "__${"%03d".format(split + 1)}.jpg"
val splitHeight = split * heightPerSplit
FileOutputStream(splitPath).use { stream -> FileOutputStream(splitPath).use { stream ->
Bitmap.createBitmap( Bitmap.createBitmap(
bitmap, bitmap,
0, 0,
split * heightPerSplit, splitHeight,
bitmap.width, bitmap.width,
heightPerSplit, min(heightPerSplit, bitmap.height - splitHeight),
).compress(Bitmap.CompressFormat.JPEG, 100, stream) ).compress(Bitmap.CompressFormat.JPEG, 100, stream)
} }
} }
imageFile.delete() imageFile.delete()
} catch (e: Exception) { } catch (e: Exception) {
// Image splits were not successfully saved so delete them and keep the original image // 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" } .map { imageFile.filePath!!.substringBeforeLast(".") + "__${"%03d".format(it + 1)}.jpg" }
.forEach { File(it).delete() } .forEach { File(it).delete() }
throw e throw e

View File

@ -19,6 +19,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.BufferedInputStream
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.InputStream import java.io.InputStream
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -238,7 +239,7 @@ class PagerPageHolder(
.subscribe({}, {}) .subscribe({}, {})
} }
private fun process(page: ReaderPage, imageStream: InputStream): InputStream { private fun process(page: ReaderPage, imageStream: BufferedInputStream): InputStream {
if (!viewer.config.dualPageSplit) { if (!viewer.config.dualPageSplit) {
return imageStream return imageStream
} }

View File

@ -23,6 +23,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.BufferedInputStream
import java.io.InputStream import java.io.InputStream
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -272,7 +273,7 @@ class WebtoonPageHolder(
addSubscription(readImageHeaderSubscription) addSubscription(readImageHeaderSubscription)
} }
private fun process(imageStream: InputStream): InputStream { private fun process(imageStream: BufferedInputStream): InputStream {
if (!viewer.config.dualPageSplit) { if (!viewer.config.dualPageSplit) {
return imageStream return imageStream
} }

View File

@ -18,6 +18,7 @@ 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 java.io.BufferedInputStream
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.io.InputStream import java.io.InputStream
@ -103,7 +104,7 @@ object ImageUtil {
* *
* @return true if the width is greater than the height * @return true if the width is greater than the height
*/ */
fun isWideImage(imageStream: InputStream): Boolean { fun isWideImage(imageStream: BufferedInputStream): Boolean {
val options = extractImageOptions(imageStream) val options = extractImageOptions(imageStream)
imageStream.reset() imageStream.reset()
return options.outWidth > options.outHeight return options.outWidth > options.outHeight