fixed crash when opening large PSD

This commit is contained in:
Thibault Deckers 2021-04-21 10:30:31 +09:00
parent fba090ae1f
commit 492d9964ad
2 changed files with 36 additions and 17 deletions

View file

@ -2,7 +2,9 @@ package deckers.thibault.aves.metadata
import android.content.Context
import android.net.Uri
import android.util.Log
import androidx.exifinterface.media.ExifInterface
import deckers.thibault.aves.utils.LogUtils
import deckers.thibault.aves.utils.MimeTypes
import deckers.thibault.aves.utils.StorageUtils
import java.io.File
@ -13,6 +15,8 @@ import java.util.*
import java.util.regex.Pattern
object Metadata {
private val LOG_TAG = LogUtils.createTag<Metadata>()
// Pattern to extract latitude & longitude from a video location tag (cf ISO 6709)
// Examples:
// "+37.5090+127.0243/" (Samsung)
@ -96,10 +100,10 @@ object Metadata {
return dateMillis
}
// opening large TIFF files yields an OOM (both with `metadata-extractor` v2.15.0 and `ExifInterface` v1.3.1),
// opening large PSD/TIFF files yields an OOM (both with `metadata-extractor` v2.15.0 and `ExifInterface` v1.3.1),
// so we define an arbitrary threshold to avoid a crash on launch.
// It is not clear whether it is because of the file itself or its metadata.
private const val tiffSizeBytesMax = 100 * (1 shl 20) // MB
private const val fileSizeBytesMax = 100 * (1 shl 20) // MB
// we try and read metadata from large files by copying an arbitrary amount from its beginning
// to a temporary file, and reusing that preview file for all metadata reading purposes
@ -108,10 +112,18 @@ object Metadata {
private val previewFiles = HashMap<Uri, File>()
private fun getSafeUri(context: Context, uri: Uri, mimeType: String, sizeBytes: Long?): Uri {
if (mimeType != MimeTypes.TIFF) return uri
if (sizeBytes != null && sizeBytes < tiffSizeBytesMax) return uri
return when (mimeType) {
// formats known to yield OOM for large files
MimeTypes.PSD_VND,
MimeTypes.PSD_X,
MimeTypes.TIFF -> {
if (sizeBytes != null && sizeBytes < fileSizeBytesMax) {
// small enough to be safe as it is
uri
} else {
// make a preview from the beginning of the file,
// hoping the metadata is accessible in the copied chunk
Log.d(LOG_TAG, "use a preview for uri=$uri mimeType=$mimeType size=$sizeBytes")
var previewFile = previewFiles[uri]
if (previewFile == null) {
previewFile = File.createTempFile("aves", null, context.cacheDir).apply {
@ -126,7 +138,12 @@ object Metadata {
}
previewFiles[uri] = previewFile
}
return Uri.fromFile(previewFile)
Uri.fromFile(previewFile)
}
}
// *probably* safe
else -> uri
}
}
fun openSafeInputStream(context: Context, uri: Uri, mimeType: String, sizeBytes: Long?): InputStream? {

View file

@ -14,6 +14,8 @@ object MimeTypes {
private const val ICO = "image/x-icon"
const val JPEG = "image/jpeg"
const val PNG = "image/png"
const val PSD_VND = "image/vnd.adobe.photoshop"
const val PSD_X = "image/x-photoshop"
const val TIFF = "image/tiff"
private const val WBMP = "image/vnd.wap.wbmp"
const val WEBP = "image/webp"