mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Handle HEIF images (partly addresses #4756)
This commit is contained in:
		@@ -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"),
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user