diff --git a/README.md b/README.md index bd6070f37628..78bc1fc69014 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,8 @@ https://discord.gg/mihon ### fix - [x] https://github.com/mihonapp/mihon/commit/d6c4af89c4a2df213f06ed4c3d714a2608117afb - [x] ~~switch from glide to coil, and use tachiyomi's image decoder~~ -- [x] include tachiyomi's image decoder for exts to use, support AVIF and HEIC +- [x] ~~include tachiyomi's image decoder for exts to use, support AVIF and HEIC~~ +- [x] include tachiyomi's image decoder as a decoder for glide, supporting AVIF, HEIC, and JXL! - [ ] recognize CBZ downloads in UI, not only in badges - [ ] fix smart background (steal from j2k) - [ ] chapter list: current page progress same color as scanlator group diff --git a/app/build.gradle b/app/build.gradle index d12457fe3a81..1c55b7cb54ed 100755 --- a/app/build.gradle +++ b/app/build.gradle @@ -257,7 +257,7 @@ dependencies { // Image library final glide_version = '4.16.0' implementation "com.github.bumptech.glide:glide:$glide_version" - implementation "com.github.bumptech.glide:avif-integration:$glide_version" + //implementation "com.github.bumptech.glide:avif-integration:$glide_version" implementation "com.github.bumptech.glide:okhttp3-integration:$glide_version" kapt "com.github.bumptech.glide:compiler:$glide_version" implementation "com.github.tachiyomiorg:image-decoder:fbd6601290" //for some exts diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/glide/TachiGlideModule.kt b/app/src/main/java/eu/kanade/tachiyomi/data/glide/TachiGlideModule.kt index 2182fa868761..f37be68ec923 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/glide/TachiGlideModule.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/glide/TachiGlideModule.kt @@ -1,6 +1,7 @@ package eu.kanade.tachiyomi.data.glide import android.content.Context +import android.graphics.Bitmap import android.graphics.drawable.Drawable import com.bumptech.glide.Glide import com.bumptech.glide.GlideBuilder @@ -15,6 +16,7 @@ import com.bumptech.glide.module.AppGlideModule import com.bumptech.glide.request.RequestOptions import eu.kanade.tachiyomi.network.NetworkHelper import java.io.InputStream +import java.nio.ByteBuffer import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -51,5 +53,17 @@ class TachiGlideModule : AppGlideModule() { InputStream::class.java, PassthroughModelLoader.Factory() ) + + registry.prepend( + ByteBuffer::class.java, + Bitmap::class.java, + TachiyomiImageDecoderGlideWrapper.ByteBufferDecoder(glide.bitmapPool) + ) + + registry.prepend( + InputStream::class.java, + Bitmap::class.java, + TachiyomiImageDecoderGlideWrapper.InputStreamDecoder(glide.bitmapPool) + ) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/glide/TachiyomiImageDecoderGlideWrapper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/glide/TachiyomiImageDecoderGlideWrapper.kt new file mode 100755 index 000000000000..b598b23d2488 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/data/glide/TachiyomiImageDecoderGlideWrapper.kt @@ -0,0 +1,61 @@ +package eu.kanade.tachiyomi.data.glide + +import android.graphics.Bitmap +import android.os.Build +import com.bumptech.glide.load.DecodeFormat +import com.bumptech.glide.load.Options +import com.bumptech.glide.load.ResourceDecoder +import com.bumptech.glide.load.engine.Resource +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool +import com.bumptech.glide.load.resource.bitmap.BitmapResource +import com.bumptech.glide.load.resource.bitmap.Downsampler +import eu.kanade.tachiyomi.util.system.ImageUtil +import java.io.ByteArrayInputStream +import java.io.InputStream +import java.nio.ByteBuffer +import tachiyomi.decoder.ImageDecoder + +class TachiyomiImageDecoderGlideWrapper { + class InputStreamDecoder(private val bitmapPool: BitmapPool) : ResourceDecoder { + + override fun handles(source: InputStream, options: Options): Boolean { + return when (ImageUtil.findImageType(source)) { + ImageUtil.ImageType.JXL, ImageUtil.ImageType.AVIF -> true + ImageUtil.ImageType.HEIF -> Build.VERSION.SDK_INT < Build.VERSION_CODES.O + else -> false + } + } + + override fun decode(source: InputStream, width: Int, height: Int, options: Options): Resource? { + val decoder = ImageDecoder.newInstance(source) + + if (decoder == null || decoder.width == 0 || decoder.height == 0) { + return null + } + + val rgb565 = options[Downsampler.DECODE_FORMAT] === DecodeFormat.PREFER_RGB_565 + val bitmap = decoder.decode(rgb565 = rgb565) + decoder.recycle() + + if (bitmap == null) { + return null + } + + return BitmapResource.obtain(bitmap, bitmapPool) + } + } + + class ByteBufferDecoder(bitmapPool: BitmapPool) : ResourceDecoder { + + private val streamDecoder = InputStreamDecoder(bitmapPool) + + override fun handles(source: ByteBuffer, options: Options): Boolean { + val sourceCopy = ByteArray(source.remaining()) + source.get(sourceCopy) + return streamDecoder.handles(ByteArrayInputStream(sourceCopy), options) + } + + override fun decode(source: ByteBuffer, width: Int, height: Int, options: Options): Resource? = + streamDecoder.decode(ByteArrayInputStream(source.array()), width, height, options) + } +} 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 b1763008bc7f..c66b5f25e774 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 @@ -28,7 +28,7 @@ object ImageUtil { fun findImageType(stream: InputStream): ImageType? { try { - val bytes = ByteArray(8) + val bytes = ByteArray(12) val length = if (stream.markSupported()) { stream.mark(bytes.size) @@ -53,6 +53,15 @@ object ImageUtil { if (bytes.compareWith("RIFF".toByteArray())) { return ImageType.WEBP } + if (bytes.comparesWithAnyOf( + listOf( + charByteArrayOf(0xFF, 0x0A), + charByteArrayOf(0x00, 0x00, 0x00, 0x0C, 0x4A, 0x58, 0x4C, 0x20, 0x0D, 0x0A, 0x87, 0x0A) + ) + ) + ) { + return ImageType.JXL + } if (bytes.compareWith("ftyp".toByteArray(), 4)) { if (bytes.compareWith("avi".toByteArray(), 8)) { return ImageType.AVIF @@ -105,6 +114,7 @@ object ImageUtil { WEBP("image/webp", "webp"), HEIF("image/heif", "heif"), AVIF("image/avif", "avif"), + JXL("image/jxl", "jxl") } // SY -->