mirror of
https://github.com/Suwayomi/Suwayomi-Server.git
synced 2026-07-13 07:44:34 -05:00
* [#1496] First conversion attempt * [#1496] Configurable conversion * Fix: allow nested configs (map) * [#1496] Support explicit `none` conversion * Use MimeUtils for provided download * [1496] Support image conversion on load for downloaded images * Lint * [#1496] Support conversion on fresh download as well Previous commit was only for already downloaded images, now also for fresh and cached * [#1496] Refactor: Move where conversion for download happens * Rewrite config handling, improve custom types * Lint * Add format to pages mutation * Lint * Standardize url encode * Lint * Config: Allow additional conversion parameters * Implement conversion quality parameter * Lint * Implement a conversion util to allow fallback readers * Add downloadConversions to api and backup, fix updateValue issues * Lint * Minor cleanup * Update libs.versions.toml --------- Co-authored-by: Syer10 <syer10@users.noreply.github.com>
This commit is contained in:
@@ -11,6 +11,7 @@ import eu.kanade.tachiyomi.source.local.LocalSource
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import libcore.net.MimeUtils
|
||||
import org.jetbrains.exposed.sql.SortOrder
|
||||
import org.jetbrains.exposed.sql.and
|
||||
import org.jetbrains.exposed.sql.selectAll
|
||||
@@ -23,8 +24,12 @@ import suwayomi.tachidesk.manga.impl.util.storage.ImageUtil
|
||||
import suwayomi.tachidesk.manga.model.table.ChapterTable
|
||||
import suwayomi.tachidesk.manga.model.table.MangaTable
|
||||
import suwayomi.tachidesk.manga.model.table.PageTable
|
||||
import suwayomi.tachidesk.util.ConversionUtil
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import javax.imageio.ImageIO
|
||||
|
||||
object Page {
|
||||
/**
|
||||
@@ -45,6 +50,7 @@ object Page {
|
||||
mangaId: Int,
|
||||
chapterIndex: Int,
|
||||
index: Int,
|
||||
format: String? = null,
|
||||
progressFlow: ((StateFlow<Int>) -> Unit)? = null,
|
||||
): Pair<InputStream, String> {
|
||||
val mangaEntry = transaction { MangaTable.selectAll().where { MangaTable.id eq mangaId }.first() }
|
||||
@@ -61,7 +67,7 @@ object Page {
|
||||
|
||||
try {
|
||||
if (chapterEntry[ChapterTable.isDownloaded]) {
|
||||
return ChapterDownloadHelper.getImage(mangaId, chapterId, index)
|
||||
return convertImageResponse(ChapterDownloadHelper.getImage(mangaId, chapterId, index), format)
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
// ignore and fetch again
|
||||
@@ -90,12 +96,15 @@ object Page {
|
||||
// is of archive format
|
||||
if (LocalSource.pageCache.containsKey(chapterEntry[ChapterTable.url])) {
|
||||
val pageStream = LocalSource.pageCache[chapterEntry[ChapterTable.url]]!![index]
|
||||
return pageStream() to (ImageUtil.findImageType { pageStream() }?.mime ?: "image/jpeg")
|
||||
return convertImageResponse(pageStream() to (ImageUtil.findImageType { pageStream() }?.mime ?: "image/jpeg"), format)
|
||||
}
|
||||
|
||||
// is of directory format
|
||||
val imageFile = File(tachiyomiPage.imageUrl!!)
|
||||
return imageFile.inputStream() to (ImageUtil.findImageType { imageFile.inputStream() }?.mime ?: "image/jpeg")
|
||||
return convertImageResponse(
|
||||
imageFile.inputStream() to (ImageUtil.findImageType { imageFile.inputStream() }?.mime ?: "image/jpeg"),
|
||||
format,
|
||||
)
|
||||
}
|
||||
|
||||
val source = getCatalogueSourceOrStub(mangaEntry[MangaTable.sourceReference])
|
||||
@@ -115,9 +124,38 @@ object Page {
|
||||
val cacheSaveDir = getChapterCachePath(mangaId, chapterId)
|
||||
|
||||
// Note: don't care about invalidating cache because OS cache is not permanent
|
||||
return getImageResponse(cacheSaveDir, fileName) {
|
||||
source.getImage(tachiyomiPage)
|
||||
return convertImageResponse(
|
||||
getImageResponse(cacheSaveDir, fileName) {
|
||||
source.getImage(tachiyomiPage)
|
||||
},
|
||||
format,
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun convertImageResponse(
|
||||
image: Pair<InputStream, String>,
|
||||
format: String? = null,
|
||||
): Pair<InputStream, String> {
|
||||
val imageExtension = MimeUtils.guessExtensionFromMimeType(image.second) ?: image.second.removePrefix("image/")
|
||||
|
||||
val targetExtension =
|
||||
(if (format != imageExtension) format else null)
|
||||
?: return image
|
||||
|
||||
val outStream = ByteArrayOutputStream()
|
||||
val writers = ImageIO.getImageWritersBySuffix(targetExtension)
|
||||
val writer = writers.next()
|
||||
ImageIO.createImageOutputStream(outStream).use { o ->
|
||||
writer.setOutput(o)
|
||||
|
||||
val inImage =
|
||||
ConversionUtil.readImage(image.first, image.second)
|
||||
?: throw NoSuchElementException("No conversion to $targetExtension possible")
|
||||
writer.write(inImage)
|
||||
}
|
||||
writer.dispose()
|
||||
val inStream = ByteArrayInputStream(outStream.toByteArray())
|
||||
return Pair(inStream.buffered(), MimeUtils.guessMimeTypeFromExtension(targetExtension) ?: "image/$targetExtension")
|
||||
}
|
||||
|
||||
/** converts 0 to "001" */
|
||||
|
||||
Reference in New Issue
Block a user