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:
parent
a9e629aea6
commit
39c0b74250
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user