multipage: heic track tiling
This commit is contained in:
parent
c332e125bb
commit
b59b323d34
5 changed files with 73 additions and 17 deletions
|
@ -5,6 +5,9 @@ import android.graphics.Rect
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.Size
|
import android.util.Size
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
|
import deckers.thibault.aves.channel.calls.fetchers.RegionFetcher
|
||||||
|
import deckers.thibault.aves.channel.calls.fetchers.ThumbnailFetcher
|
||||||
|
import deckers.thibault.aves.channel.calls.fetchers.TiffRegionFetcher
|
||||||
import deckers.thibault.aves.model.ExifOrientationOp
|
import deckers.thibault.aves.model.ExifOrientationOp
|
||||||
import deckers.thibault.aves.model.provider.FieldMap
|
import deckers.thibault.aves.model.provider.FieldMap
|
||||||
import deckers.thibault.aves.model.provider.ImageProvider.ImageOpCallback
|
import deckers.thibault.aves.model.provider.ImageProvider.ImageOpCallback
|
||||||
|
@ -102,19 +105,20 @@ class ImageFileHandler(private val activity: Activity) : MethodCallHandler {
|
||||||
val regionRect = Rect(x, y, x + width, y + height)
|
val regionRect = Rect(x, y, x + width, y + height)
|
||||||
when (mimeType) {
|
when (mimeType) {
|
||||||
MimeTypes.TIFF -> TiffRegionFetcher(activity).fetch(
|
MimeTypes.TIFF -> TiffRegionFetcher(activity).fetch(
|
||||||
uri,
|
uri = uri,
|
||||||
sampleSize,
|
|
||||||
regionRect,
|
|
||||||
page = pageId ?: 0,
|
page = pageId ?: 0,
|
||||||
result,
|
sampleSize = sampleSize,
|
||||||
|
regionRect = regionRect,
|
||||||
|
result = result,
|
||||||
)
|
)
|
||||||
else -> regionFetcher.fetch(
|
else -> regionFetcher.fetch(
|
||||||
uri,
|
uri = uri,
|
||||||
mimeType,
|
mimeType = mimeType,
|
||||||
sampleSize,
|
pageId = pageId,
|
||||||
regionRect,
|
sampleSize = sampleSize,
|
||||||
Size(imageWidth, imageHeight),
|
regionRect = regionRect,
|
||||||
result,
|
imageSize = Size(imageWidth, imageHeight),
|
||||||
|
result = result,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,22 @@
|
||||||
package deckers.thibault.aves.channel.calls
|
package deckers.thibault.aves.channel.calls.fetchers
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.graphics.BitmapRegionDecoder
|
import android.graphics.BitmapRegionDecoder
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.Size
|
import android.util.Size
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.bumptech.glide.load.DecodeFormat
|
||||||
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
|
import com.bumptech.glide.request.RequestOptions
|
||||||
|
import deckers.thibault.aves.decoder.MultiTrackImage
|
||||||
import deckers.thibault.aves.utils.BitmapUtils.getBytes
|
import deckers.thibault.aves.utils.BitmapUtils.getBytes
|
||||||
import deckers.thibault.aves.utils.MimeTypes
|
import deckers.thibault.aves.utils.MimeTypes
|
||||||
import deckers.thibault.aves.utils.StorageUtils
|
import deckers.thibault.aves.utils.StorageUtils
|
||||||
import io.flutter.plugin.common.MethodChannel
|
import io.flutter.plugin.common.MethodChannel
|
||||||
|
import java.io.File
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class RegionFetcher internal constructor(
|
class RegionFetcher internal constructor(
|
||||||
|
@ -17,21 +24,42 @@ class RegionFetcher internal constructor(
|
||||||
) {
|
) {
|
||||||
private var lastDecoderRef: LastDecoderRef? = null
|
private var lastDecoderRef: LastDecoderRef? = null
|
||||||
|
|
||||||
|
private val pageTempUris = HashMap<Pair<Uri, Int>, Uri>()
|
||||||
|
|
||||||
|
private val multiTrackGlideOptions = RequestOptions()
|
||||||
|
.format(DecodeFormat.PREFER_ARGB_8888)
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
|
.skipMemoryCache(true)
|
||||||
|
|
||||||
fun fetch(
|
fun fetch(
|
||||||
uri: Uri,
|
uri: Uri,
|
||||||
mimeType: String,
|
mimeType: String,
|
||||||
|
pageId: Int?,
|
||||||
sampleSize: Int,
|
sampleSize: Int,
|
||||||
regionRect: Rect,
|
regionRect: Rect,
|
||||||
imageSize: Size,
|
imageSize: Size,
|
||||||
result: MethodChannel.Result,
|
result: MethodChannel.Result,
|
||||||
) {
|
) {
|
||||||
|
if (MimeTypes.isHeifLike(mimeType) && pageId != null) {
|
||||||
|
val id = Pair(uri, pageId)
|
||||||
|
fetch(
|
||||||
|
uri = pageTempUris.getOrPut(id) { createJpegForPage(uri, pageId) },
|
||||||
|
mimeType = MimeTypes.JPEG,
|
||||||
|
pageId = null,
|
||||||
|
sampleSize = sampleSize,
|
||||||
|
regionRect = regionRect,
|
||||||
|
imageSize = imageSize,
|
||||||
|
result = result,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val options = BitmapFactory.Options().apply {
|
val options = BitmapFactory.Options().apply {
|
||||||
inSampleSize = sampleSize
|
inSampleSize = sampleSize
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentDecoderRef = lastDecoderRef
|
var currentDecoderRef = lastDecoderRef
|
||||||
if (currentDecoderRef != null && currentDecoderRef.uri != uri) {
|
if (currentDecoderRef != null && currentDecoderRef.uri != uri) {
|
||||||
currentDecoderRef.decoder.recycle()
|
|
||||||
currentDecoderRef = null
|
currentDecoderRef = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +102,31 @@ class RegionFetcher internal constructor(
|
||||||
result.error("getRegion-read-exception", "failed to initialize region decoder for uri=$uri regionRect=$regionRect", e.message)
|
result.error("getRegion-read-exception", "failed to initialize region decoder for uri=$uri regionRect=$regionRect", e.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createJpegForPage(sourceUri: Uri, pageId: Int): Uri {
|
||||||
|
val target = Glide.with(context)
|
||||||
|
.asBitmap()
|
||||||
|
.apply(multiTrackGlideOptions)
|
||||||
|
.load(MultiTrackImage(context, sourceUri, pageId))
|
||||||
|
.submit()
|
||||||
|
try {
|
||||||
|
val bitmap = target.get()
|
||||||
|
// if (MimeTypes.needRotationAfterGlide(sourceMimeType)) {
|
||||||
|
// bitmap = BitmapUtils.applyExifOrientation(context, bitmap, sourceEntry.rotationDegrees, sourceEntry.isFlipped)
|
||||||
|
// }
|
||||||
|
bitmap ?: throw Exception("failed to get image from uri=$sourceUri page=$pageId")
|
||||||
|
|
||||||
|
val tempFile = File.createTempFile("aves", null, context.cacheDir).apply {
|
||||||
|
deleteOnExit()
|
||||||
|
outputStream().use { outputStream ->
|
||||||
|
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Uri.fromFile(tempFile)
|
||||||
|
} finally {
|
||||||
|
Glide.with(context).clear(target)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class LastDecoderRef(
|
private data class LastDecoderRef(
|
|
@ -1,4 +1,4 @@
|
||||||
package deckers.thibault.aves.channel.calls
|
package deckers.thibault.aves.channel.calls.fetchers
|
||||||
|
|
||||||
import android.content.ContentUris
|
import android.content.ContentUris
|
||||||
import android.content.Context
|
import android.content.Context
|
|
@ -1,4 +1,4 @@
|
||||||
package deckers.thibault.aves.channel.calls
|
package deckers.thibault.aves.channel.calls.fetchers
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
|
@ -13,9 +13,9 @@ class TiffRegionFetcher internal constructor(
|
||||||
) {
|
) {
|
||||||
fun fetch(
|
fun fetch(
|
||||||
uri: Uri,
|
uri: Uri,
|
||||||
|
page: Int,
|
||||||
sampleSize: Int,
|
sampleSize: Int,
|
||||||
regionRect: Rect,
|
regionRect: Rect,
|
||||||
page: Int = 0,
|
|
||||||
result: MethodChannel.Result,
|
result: MethodChannel.Result,
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
|
@ -227,8 +227,7 @@ class AvesEntry {
|
||||||
MimeTypes.rw2,
|
MimeTypes.rw2,
|
||||||
MimeTypes.srw,
|
MimeTypes.srw,
|
||||||
].contains(mimeType) &&
|
].contains(mimeType) &&
|
||||||
!isAnimated &&
|
!isAnimated;
|
||||||
pageId == null;
|
|
||||||
|
|
||||||
bool get supportTiling => _supportedByBitmapRegionDecoder || mimeType == MimeTypes.tiff;
|
bool get supportTiling => _supportedByBitmapRegionDecoder || mimeType == MimeTypes.tiff;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue