multipage: heic track tiling

This commit is contained in:
Thibault Deckers 2021-01-25 18:21:18 +09:00
parent c332e125bb
commit b59b323d34
5 changed files with 73 additions and 17 deletions

View file

@ -5,6 +5,9 @@ import android.graphics.Rect
import android.net.Uri
import android.util.Size
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.provider.FieldMap
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)
when (mimeType) {
MimeTypes.TIFF -> TiffRegionFetcher(activity).fetch(
uri,
sampleSize,
regionRect,
uri = uri,
page = pageId ?: 0,
result,
sampleSize = sampleSize,
regionRect = regionRect,
result = result,
)
else -> regionFetcher.fetch(
uri,
mimeType,
sampleSize,
regionRect,
Size(imageWidth, imageHeight),
result,
uri = uri,
mimeType = mimeType,
pageId = pageId,
sampleSize = sampleSize,
regionRect = regionRect,
imageSize = Size(imageWidth, imageHeight),
result = result,
)
}
}

View file

@ -1,15 +1,22 @@
package deckers.thibault.aves.channel.calls
package deckers.thibault.aves.channel.calls.fetchers
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.BitmapRegionDecoder
import android.graphics.Rect
import android.net.Uri
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.MimeTypes
import deckers.thibault.aves.utils.StorageUtils
import io.flutter.plugin.common.MethodChannel
import java.io.File
import kotlin.math.roundToInt
class RegionFetcher internal constructor(
@ -17,21 +24,42 @@ class RegionFetcher internal constructor(
) {
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(
uri: Uri,
mimeType: String,
pageId: Int?,
sampleSize: Int,
regionRect: Rect,
imageSize: Size,
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 {
inSampleSize = sampleSize
}
var currentDecoderRef = lastDecoderRef
if (currentDecoderRef != null && currentDecoderRef.uri != uri) {
currentDecoderRef.decoder.recycle()
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)
}
}
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(

View file

@ -1,4 +1,4 @@
package deckers.thibault.aves.channel.calls
package deckers.thibault.aves.channel.calls.fetchers
import android.content.ContentUris
import android.content.Context

View file

@ -1,4 +1,4 @@
package deckers.thibault.aves.channel.calls
package deckers.thibault.aves.channel.calls.fetchers
import android.content.Context
import android.graphics.Rect
@ -13,9 +13,9 @@ class TiffRegionFetcher internal constructor(
) {
fun fetch(
uri: Uri,
page: Int,
sampleSize: Int,
regionRect: Rect,
page: Int = 0,
result: MethodChannel.Result,
) {
try {

View file

@ -227,8 +227,7 @@ class AvesEntry {
MimeTypes.rw2,
MimeTypes.srw,
].contains(mimeType) &&
!isAnimated &&
pageId == null;
!isAnimated;
bool get supportTiling => _supportedByBitmapRegionDecoder || mimeType == MimeTypes.tiff;