Refactor Image source provider

Skia use SKMemoryStream to read file mapping data
SKMemoryStream always use memcpy to emulate posix read stream behaviour, cannot take advantages of file mapping reading

* https://github.com/google/skia/blob/1f193df9b393d50da39570dab77a0bb5d28ec8ef/src/core/SkStream.cpp#L335
This commit is contained in:
tarsin committed 2023-02-13 18:21:57 +08:00
1 parent 0e6156e51c
commit d30379251d
5 files changed
+47 -85

No files matched your search

+12 -16
View File
@@ -21,7 +21,7 @@ import android.graphics.ColorSpace
import android.graphics.ImageDecoder
import android.graphics.ImageDecoder.ImageInfo
import android.graphics.ImageDecoder.Source
import android.graphics.drawable.Animatable
import android.graphics.drawable.AnimatedImageDrawable
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.os.Build
@@ -30,9 +30,9 @@ import com.hippo.ehviewer.R
import java.nio.ByteBuffer
import kotlin.math.min
class Image private constructor(source: Source, private var src: ByteBufferSource?) {
class Image private constructor(private val src: CloseableSource) {
var mObtainedDrawable: Drawable? =
ImageDecoder.decodeDrawable(source) { decoder: ImageDecoder, info: ImageInfo, _: Source ->
ImageDecoder.decodeDrawable(src.source) { decoder: ImageDecoder, info: ImageInfo, _: Source ->
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.P) {
// Allocating hardware bitmap may cause a crash on framework versions prior to Android Q
decoder.allocator = ImageDecoder.ALLOCATOR_SOFTWARE
@@ -43,23 +43,21 @@ class Image private constructor(source: Source, private var src: ByteBufferSourc
)
}.also {
(it as? BitmapDrawable)?.run {
src?.close()
src = null
src.close()
}
}
private set
val size: Int
get() = mObtainedDrawable!!.run { intrinsicHeight * intrinsicWidth * 4 * if (this is Animatable) 4 else 1 }
get() = mObtainedDrawable!!.run { intrinsicHeight * intrinsicWidth * 4 * if (this is AnimatedImageDrawable) 4 else 1 }
@Synchronized
fun recycle() {
(mObtainedDrawable as? Animatable)?.stop()
(mObtainedDrawable as? AnimatedImageDrawable)?.stop()
(mObtainedDrawable as? BitmapDrawable)?.bitmap?.recycle()
mObtainedDrawable?.callback = null
mObtainedDrawable = null
src?.close()
src = null
(mObtainedDrawable as? AnimatedImageDrawable)?.let { src.close() }
}
companion object {
@@ -91,10 +89,9 @@ class Image private constructor(source: Source, private var src: ByteBufferSourc
)
@JvmStatic
fun decode(src: ByteBufferSource): Image? {
val directBuffer = src.getByteBuffer()
fun decode(src: CloseableSource): Image? {
return runCatching {
Image(ImageDecoder.createSource(directBuffer), src)
Image(src)
}.onFailure {
src.close()
it.printStackTrace()
@@ -105,8 +102,7 @@ class Image private constructor(source: Source, private var src: ByteBufferSourc
external fun rewriteGifSource(buffer: ByteBuffer)
}
interface ByteBufferSource : AutoCloseable {
// A read-write direct bytebuffer, it may in native heap or file mapping
fun getByteBuffer(): ByteBuffer
interface CloseableSource : AutoCloseable {
val source: Source
}
}
}