fix: Do not return inputStream from conversion & handle conversion error (#1854)

* fix: Do not return `inputStream` from conversion

The returned value must be owned, since the caller closes the input
stream on success

* fix: Assume a conversion error consumes the input stream

e.g. converting an ARGB png to jpeg will throw "bogus colorspace", but
only after the inputstream is consumed. so in case of an exception, we
have to assume that the stream is broken and re-open the page from cache
This commit is contained in:
Constantin Piber
2026-01-11 22:48:16 +01:00
committed by GitHub
parent c4d8bba5ca
commit 02da884f17

View File

@@ -169,7 +169,9 @@ object Page {
)
} catch (e: Exception) {
logger.error(e) { "Error while post-processing image" }
null
// re-open cached image in case of an error, since conversion likely (partially) consumed the input stream
// so it's likely not possible to serve it
getPageImage(mangaId = mangaId, chapterIndex = chapterIndex, index = index)
}
return converted?.also { inputStream.close() } ?: (inputStream to mime)
}
@@ -269,11 +271,12 @@ object Page {
return processedStream to mime
}
throw Exception("HTTP-service did not return a usable stream")
} catch (e: Exception) {
// HTTP post-processing failed, continue with original image
logger.warn(e) { "Error while post-processing image" }
throw e
}
return null
} else {
if (mime == conversion.target) {
return null
@@ -296,7 +299,7 @@ object Page {
)
if (conversionWriter == null) {
logger.warn { "Conversion aborted: No reader for target format ${target.target}" }
return inputStream to sourceMimeType
return null
}
val (writer, writerParams) = conversionWriter
@@ -310,13 +313,13 @@ object Page {
writer.write(null, IIOImage(inImage, null, null), writerParams)
}
} catch (e: Exception) {
logger.warn(e) { "Conversion aborted" }
return null
logger.warn(e) { "Conversion aborted ($sourceMimeType -> ${target.target})" }
throw e
} finally {
writer.dispose()
}
val inStream = ByteArrayInputStream(outStream.toByteArray())
return Pair(inStream.buffered(), target.target)
return inStream.buffered() to target.target
}
private fun getConversionWriter(