From 74381ef59e9c05129d77e82dac17ab0f0b9e3406 Mon Sep 17 00:00:00 2001 From: arkon Date: Fri, 4 Jun 2021 23:26:37 -0400 Subject: [PATCH] Handle HEIF images (partly addresses #4756) --- .../kanade/tachiyomi/util/system/ImageUtil.kt | 77 +++++++------------ 1 file changed, 28 insertions(+), 49 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/ImageUtil.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/ImageUtil.kt index 6d82108186..00771ea77f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/ImageUtil.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/ImageUtil.kt @@ -18,6 +18,7 @@ import androidx.core.graphics.green import androidx.core.graphics.red import tachiyomi.decoder.Format import tachiyomi.decoder.ImageDecoder +import tachiyomi.decoder.ImageType import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.InputStream @@ -41,30 +42,14 @@ object ImageUtil { fun findImageType(stream: InputStream): ImageType? { try { - val bytes = ByteArray(8) - - val length = if (stream.markSupported()) { - stream.mark(bytes.size) - stream.read(bytes, 0, bytes.size).also { stream.reset() } - } else { - stream.read(bytes, 0, bytes.size) - } - - if (length == -1) { - return null - } - - if (bytes.compareWith(charByteArrayOf(0xFF, 0xD8, 0xFF))) { - return ImageType.JPG - } - if (bytes.compareWith(charByteArrayOf(0x89, 0x50, 0x4E, 0x47))) { - return ImageType.PNG - } - if (bytes.compareWith("GIF8".toByteArray())) { - return ImageType.GIF - } - if (bytes.compareWith("RIFF".toByteArray())) { - return ImageType.WEBP + return when (getImageType(stream)?.format) { + // TODO: image-decoder library currently doesn't detect this + // Format.Avif -> ImageType.AVIF + Format.Gif -> ImageType.GIF + Format.Heif -> ImageType.HEIF + Format.Jpeg -> ImageType.JPEG + Format.Png -> ImageType.PNG + Format.Webp -> ImageType.WEBP } } catch (e: Exception) { } @@ -73,20 +58,7 @@ object ImageUtil { fun isAnimatedAndSupported(stream: InputStream): Boolean { try { - val bytes = ByteArray(32) - - val length = if (stream.markSupported()) { - stream.mark(bytes.size) - stream.read(bytes, 0, bytes.size).also { stream.reset() } - } else { - stream.read(bytes, 0, bytes.size) - } - - if (length == -1) { - return false - } - - val type = ImageDecoder.findType(bytes) ?: return false + val type = getImageType(stream) ?: return false return when (type.format) { Format.Gif -> true // Coil supports animated WebP on Android 9.0+ @@ -99,23 +71,30 @@ object ImageUtil { return false } - private fun ByteArray.compareWith(magic: ByteArray): Boolean { - return magic.indices.none { this[it] != magic[it] } - } + private fun getImageType(stream: InputStream): tachiyomi.decoder.ImageType? { + val bytes = ByteArray(32) - private fun charByteArrayOf(vararg bytes: Int): ByteArray { - return ByteArray(bytes.size).apply { - for (i in bytes.indices) { - set(i, bytes[i].toByte()) - } + val length = if (stream.markSupported()) { + stream.mark(bytes.size) + stream.read(bytes, 0, bytes.size).also { stream.reset() } + } else { + stream.read(bytes, 0, bytes.size) } + + if (length == -1) { + return null + } + + return ImageDecoder.findType(bytes) } enum class ImageType(val mime: String, val extension: String) { - JPG("image/jpeg", "jpg"), - PNG("image/png", "png"), + // AVIF("image/avif", "avif"), GIF("image/gif", "gif"), - WEBP("image/webp", "webp") + HEIF("image/heif", "heif"), + JPEG("image/jpeg", "jpg"), + PNG("image/png", "png"), + WEBP("image/webp", "webp"), } /**