diff --git a/CHANGELOG.md b/CHANGELOG.md index 41cae794a..423592307 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co ### Removed - Remove "Custom hardware bitmap threshold" and "Custom display profile" advanced settings ([@wwww-wwww](https://github.com/wwww-wwww)) ([#3786](https://github.com/mihonapp/mihon/pull/3786)) +- Remove the "Split tall images" download setting ([@AntsyLich](https://github.com/AntsyLich)) ## [v0.21.2] - 2026-10-13 ### Fixed diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsDownloadScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsDownloadScreen.kt index 7dfbd604d..17035b8db 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsDownloadScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsDownloadScreen.kt @@ -43,11 +43,6 @@ object SettingsDownloadScreen : SearchableSettings { preference = downloadPreferences.saveChaptersAsCBZ, title = stringResource(MR.strings.save_chapter_as_cbz), ), - Preference.PreferenceItem.SwitchPreference( - preference = downloadPreferences.splitTallImages, - title = stringResource(MR.strings.split_tall_images), - subtitle = stringResource(MR.strings.split_tall_images_summary), - ), Preference.PreferenceItem.SliderPreference( preference = downloadPreferences.parallelSourceLimit, valueRange = 1..10, 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 105c153ef..ca17339b8 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 @@ -551,8 +551,6 @@ class Downloader( } // When the page is ready, set page path, progress (just in case) and status - splitTallImageIfNeeded(page, tmpDir) - page.uri = file.uri page.progress = 100 page.status = Page.State.Ready @@ -645,23 +643,6 @@ class Downloader( return ImageUtil.getExtensionFromMimeType(mime) { file.openInputStream() } } - private fun splitTallImageIfNeeded(page: Page, tmpDir: UniFile) { - if (!downloadPreferences.splitTallImages.get()) return - - try { - val filenamePrefix = "%03d".format(Locale.ENGLISH, page.number) - val imageFile = tmpDir.listFiles()?.firstOrNull { it.name.orEmpty().startsWith(filenamePrefix) } - ?: error(context.stringResource(MR.strings.download_notifier_split_page_not_found, page.number)) - - // If the original page was previously split, then skip - if (imageFile.name.orEmpty().startsWith("${filenamePrefix}__")) return - - ImageUtil.splitTallImage(tmpDir, imageFile, filenamePrefix) - } catch (e: Exception) { - logcat(LogPriority.ERROR, e) { "Failed to split downloaded image" } - } - } - /** * Checks if the download was successful. * diff --git a/core/common/src/main/kotlin/tachiyomi/core/common/util/system/ImageUtil.kt b/core/common/src/main/kotlin/tachiyomi/core/common/util/system/ImageUtil.kt index b40468474..fdf0568ee 100644 --- a/core/common/src/main/kotlin/tachiyomi/core/common/util/system/ImageUtil.kt +++ b/core/common/src/main/kotlin/tachiyomi/core/common/util/system/ImageUtil.kt @@ -185,120 +185,6 @@ object ImageUtil { LEFT, } - /** - * Check whether the image is considered a tall image. - * - * @return true if the height:width ratio is greater than 3. - */ - private fun isTallImage(imageSource: BufferedSource): Boolean { - val options = extractImageOptions(imageSource) - return TallImageSplitCalculator.shouldSplit( - imageWidth = options.outWidth, - imageHeight = options.outHeight, - optimalImageHeight = optimalImageHeight, - ) - } - - /** - * Splits tall images to improve performance of reader - */ - fun splitTallImage(tmpDir: UniFile, imageFile: UniFile, filenamePrefix: String): Boolean { - val imageSource = imageFile.openInputStream().use { Buffer().readFrom(it) } - if (isAnimatedAndSupported(imageSource) || !isTallImage(imageSource)) { - return true - } - - val bitmapRegionDecoder = getBitmapRegionDecoder(imageSource.peek().inputStream()) - if (bitmapRegionDecoder == null) { - logcat { "Failed to create new instance of BitmapRegionDecoder" } - return false - } - - val options = extractImageOptions(imageSource).apply { - inJustDecodeBounds = false - } - val splitDataList = options.splitData - - return try { - splitDataList.forEach { splitData -> - val splitImageName = splitImageName(filenamePrefix, splitData.index) - // Remove pre-existing split if exists (this split shouldn't exist under normal circumstances) - tmpDir.findFile(splitImageName)?.delete() - - val splitFile = tmpDir.createFile(splitImageName)!! - - val region = Rect(0, splitData.topOffset, splitData.splitWidth, splitData.bottomOffset) - - splitFile.openOutputStream().use { outputStream -> - val splitBitmap = bitmapRegionDecoder.decodeRegion(region, options) - splitBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream) - splitBitmap.recycle() - } - logcat { - "Success: Split #${splitData.index + 1} with topOffset=${splitData.topOffset} " + - "height=${splitData.splitHeight} bottomOffset=${splitData.bottomOffset}" - } - } - imageFile.delete() - true - } catch (e: Exception) { - // Image splits were not successfully saved so delete them and keep the original image - splitDataList - .map { splitImageName(filenamePrefix, it.index) } - .forEach { tmpDir.findFile(it)?.delete() } - logcat(LogPriority.ERROR, e) - false - } finally { - bitmapRegionDecoder.recycle() - } - } - - private fun splitImageName(filenamePrefix: String, index: Int) = "${filenamePrefix}__${"%03d".format( - Locale.ENGLISH, - index + 1, - )}.jpg" - - private val BitmapFactory.Options.splitData - get(): List { - val imageHeight = outHeight - val imageWidth = outWidth - - val partCount = TallImageSplitCalculator.calculatePartCount(imageHeight, optimalImageHeight) - val optimalSplitHeight = imageHeight / partCount - - logcat { - "Generating SplitData for image (height: $imageHeight): " + - "$partCount parts @ ${optimalSplitHeight}px height per part" - } - - return buildList { - val range = 0..= Build.VERSION_CODES.S) { - BitmapRegionDecoder.newInstance(imageStream) - } else { - @Suppress("DEPRECATION") - BitmapRegionDecoder.newInstance(imageStream, false) - } - } - - private val optimalImageHeight = getDisplayMaxHeightInPx * 2 } - -val getDisplayMaxHeightInPx: Int - get() = Resources.getSystem().displayMetrics.let { max(it.heightPixels, it.widthPixels) } diff --git a/core/common/src/main/kotlin/tachiyomi/core/common/util/system/TallImageSplitCalculator.kt b/core/common/src/main/kotlin/tachiyomi/core/common/util/system/TallImageSplitCalculator.kt deleted file mode 100644 index 9613812ae..000000000 --- a/core/common/src/main/kotlin/tachiyomi/core/common/util/system/TallImageSplitCalculator.kt +++ /dev/null @@ -1,17 +0,0 @@ -package tachiyomi.core.common.util.system - -internal object TallImageSplitCalculator { - - fun calculatePartCount(imageHeight: Int, optimalImageHeight: Int): Int { - require(imageHeight > 0) { "imageHeight must be positive" } - require(optimalImageHeight > 0) { "optimalImageHeight must be positive" } - // -1 so it doesn't try to split when imageHeight = optimalImageHeight - return (imageHeight - 1) / optimalImageHeight + 1 - } - - fun shouldSplit(imageWidth: Int, imageHeight: Int, optimalImageHeight: Int): Boolean { - require(imageWidth > 0) { "imageWidth must be positive" } - return imageHeight > imageWidth * 3 && - calculatePartCount(imageHeight, optimalImageHeight) > 1 - } -} diff --git a/core/common/src/test/java/tachiyomi/core/common/util/system/TallImageSplitCalculatorTest.kt b/core/common/src/test/java/tachiyomi/core/common/util/system/TallImageSplitCalculatorTest.kt deleted file mode 100644 index dd3f7a560..000000000 --- a/core/common/src/test/java/tachiyomi/core/common/util/system/TallImageSplitCalculatorTest.kt +++ /dev/null @@ -1,37 +0,0 @@ -package tachiyomi.core.common.util.system - -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertFalse -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test - -class TallImageSplitCalculatorTest { - - @Test - fun `does not split when aspect ratio is tall but computed split count is one`() { - assertFalse( - TallImageSplitCalculator.shouldSplit( - imageWidth = 1024, - imageHeight = 4385, - optimalImageHeight = 4386, - ), - ) - } - - @Test - fun `splits when aspect ratio is tall and computed split count is greater than one`() { - assertTrue( - TallImageSplitCalculator.shouldSplit( - imageWidth = 1024, - imageHeight = 4385, - optimalImageHeight = 4384, - ), - ) - } - - @Test - fun `calculate part count rounds boundary correctly`() { - assertEquals(1, TallImageSplitCalculator.calculatePartCount(imageHeight = 4384, optimalImageHeight = 4384)) - assertEquals(2, TallImageSplitCalculator.calculatePartCount(imageHeight = 4385, optimalImageHeight = 4384)) - } -} diff --git a/domain/src/main/java/tachiyomi/domain/download/service/DownloadPreferences.kt b/domain/src/main/java/tachiyomi/domain/download/service/DownloadPreferences.kt index 5795dc89e..d2fb65a67 100644 --- a/domain/src/main/java/tachiyomi/domain/download/service/DownloadPreferences.kt +++ b/domain/src/main/java/tachiyomi/domain/download/service/DownloadPreferences.kt @@ -19,8 +19,6 @@ class DownloadPreferences( val saveChaptersAsCBZ: Preference = preferenceStore.getBoolean("save_chapter_as_cbz", true) - val splitTallImages: Preference = preferenceStore.getBoolean("split_tall_images", true) - val autoDownloadWhileReading: Preference = preferenceStore.getInt("auto_download_while_reading", 0) val removeAfterReadSlots: Preference = preferenceStore.getInt("remove_after_read_slots", -1) diff --git a/i18n/src/commonMain/moko-resources/base/strings.xml b/i18n/src/commonMain/moko-resources/base/strings.xml index 4474f5c77..f141009ba 100644 --- a/i18n/src/commonMain/moko-resources/base/strings.xml +++ b/i18n/src/commonMain/moko-resources/base/strings.xml @@ -577,8 +577,6 @@ Auto download while reading Only works if the current chapter + the next one are already downloaded. Save as CBZ archive - Split tall images - Improves reader performance Concurrent source downloads Concurrent page downloads Pages downloaded simultaneously per source @@ -1038,7 +1036,6 @@ No Wi-Fi connection available No network connection available Downloads paused - Page %d not found while splitting Couldn\'t find file path of page %d Checking downloads