Display animated webp whenever possible, otherwise fallback to static image. Fixes #5139
This commit is contained in:
parent
9a801cfdfb
commit
8c18a14dfd
@ -205,7 +205,10 @@ dependencies {
|
|||||||
implementation("io.coil-kt:coil:$coilVersion")
|
implementation("io.coil-kt:coil:$coilVersion")
|
||||||
implementation("io.coil-kt:coil-gif:$coilVersion")
|
implementation("io.coil-kt:coil-gif:$coilVersion")
|
||||||
|
|
||||||
implementation("com.github.tachiyomiorg:subsampling-scale-image-view:846abe0")
|
implementation("com.github.tachiyomiorg:subsampling-scale-image-view:846abe0") {
|
||||||
|
exclude(module = "image-decoder")
|
||||||
|
}
|
||||||
|
implementation("com.github.tachiyomiorg:image-decoder:e6d680f")
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
implementation("com.jakewharton.timber:timber:4.7.1")
|
implementation("com.jakewharton.timber:timber:4.7.1")
|
||||||
|
@ -232,7 +232,7 @@ class PagerPageHolder(
|
|||||||
val stream = streamFn().buffered(16)
|
val stream = streamFn().buffered(16)
|
||||||
openStream = process(item, stream)
|
openStream = process(item, stream)
|
||||||
|
|
||||||
ImageUtil.findImageType(stream) == ImageUtil.ImageType.GIF
|
ImageUtil.isAnimatedAndSupported(stream)
|
||||||
}
|
}
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
@ -279,7 +279,7 @@ class WebtoonPageHolder(
|
|||||||
val stream = streamFn().buffered(16)
|
val stream = streamFn().buffered(16)
|
||||||
openStream = process(stream)
|
openStream = process(stream)
|
||||||
|
|
||||||
ImageUtil.findImageType(stream) == ImageUtil.ImageType.GIF
|
ImageUtil.isAnimatedAndSupported(stream)
|
||||||
}
|
}
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
@ -10,11 +10,14 @@ import android.graphics.Rect
|
|||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.ColorDrawable
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.graphics.drawable.GradientDrawable
|
import android.graphics.drawable.GradientDrawable
|
||||||
|
import android.os.Build
|
||||||
import androidx.core.graphics.alpha
|
import androidx.core.graphics.alpha
|
||||||
import androidx.core.graphics.blue
|
import androidx.core.graphics.blue
|
||||||
import androidx.core.graphics.createBitmap
|
import androidx.core.graphics.createBitmap
|
||||||
import androidx.core.graphics.green
|
import androidx.core.graphics.green
|
||||||
import androidx.core.graphics.red
|
import androidx.core.graphics.red
|
||||||
|
import tachiyomi.decoder.Format
|
||||||
|
import tachiyomi.decoder.ImageDecoder
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
@ -68,6 +71,34 @@ object ImageUtil {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
return when (type.format) {
|
||||||
|
Format.Gif -> true
|
||||||
|
// Coil supports animated WebP on Android 9.0+
|
||||||
|
// https://coil-kt.github.io/coil/getting_started/#supported-image-formats
|
||||||
|
Format.Webp -> type.isAnimated && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
private fun ByteArray.compareWith(magic: ByteArray): Boolean {
|
private fun ByteArray.compareWith(magic: ByteArray): Boolean {
|
||||||
return magic.indices.none { this[it] != magic[it] }
|
return magic.indices.none { this[it] != magic[it] }
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user