fixed crash when cataloguing large TIFF
This commit is contained in:
parent
a3436bfdf3
commit
b02aec53e5
8 changed files with 19 additions and 18 deletions
|
@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
- wrong window metrics on startup in some cases
|
||||
- home albums not updated on startup in some cases
|
||||
- crash when cataloguing large TIFF
|
||||
|
||||
## <a id="v1.6.7"></a>[v1.6.7] - 2022-05-25
|
||||
|
||||
|
|
|
@ -284,7 +284,7 @@ class DebugHandler(private val context: Context) : MethodCallHandler {
|
|||
if (canReadWithMetadataExtractor(mimeType)) {
|
||||
try {
|
||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||
val metadata = MetadataExtractorHelper.safeRead(input, sizeBytes)
|
||||
val metadata = MetadataExtractorHelper.safeRead(input)
|
||||
metadataMap["mimeType"] = metadata.getDirectoriesOfType(FileTypeDirectory::class.java).joinToString { dir ->
|
||||
if (dir.containsTag(FileTypeDirectory.TAG_DETECTED_FILE_MIME_TYPE)) {
|
||||
dir.getString(FileTypeDirectory.TAG_DETECTED_FILE_MIME_TYPE)
|
||||
|
|
|
@ -150,7 +150,7 @@ class EmbeddedDataHandler(private val context: Context) : MethodCallHandler {
|
|||
if (canReadWithMetadataExtractor(mimeType)) {
|
||||
try {
|
||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||
val metadata = MetadataExtractorHelper.safeRead(input, sizeBytes)
|
||||
val metadata = MetadataExtractorHelper.safeRead(input)
|
||||
// data can be large and stored in "Extended XMP",
|
||||
// which is returned as a second XMP directory
|
||||
val xmpDirs = metadata.getDirectoriesOfType(XmpDirectory::class.java)
|
||||
|
|
|
@ -126,7 +126,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
|||
if (canReadWithMetadataExtractor(mimeType)) {
|
||||
try {
|
||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||
val metadata = MetadataExtractorHelper.safeRead(input, sizeBytes)
|
||||
val metadata = MetadataExtractorHelper.safeRead(input)
|
||||
foundExif = metadata.directories.any { it is ExifDirectoryBase && it.tagCount > 0 }
|
||||
foundXmp = metadata.directories.any { it is XmpDirectory && it.tagCount > 0 }
|
||||
val uuidDirCount = HashMap<String, Int>()
|
||||
|
@ -451,7 +451,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
|||
if (canReadWithMetadataExtractor(mimeType)) {
|
||||
try {
|
||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||
val metadata = MetadataExtractorHelper.safeRead(input, sizeBytes)
|
||||
val metadata = MetadataExtractorHelper.safeRead(input)
|
||||
foundExif = metadata.directories.any { it is ExifDirectoryBase && it.tagCount > 0 }
|
||||
|
||||
// File type
|
||||
|
@ -718,7 +718,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
|||
if (canReadWithMetadataExtractor(mimeType)) {
|
||||
try {
|
||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||
val metadata = MetadataExtractorHelper.safeRead(input, sizeBytes)
|
||||
val metadata = MetadataExtractorHelper.safeRead(input)
|
||||
for (dir in metadata.getDirectoriesOfType(ExifSubIFDDirectory::class.java)) {
|
||||
foundExif = true
|
||||
dir.getSafeRational(ExifDirectoryBase.TAG_FNUMBER) { metadataMap[KEY_APERTURE] = it.numerator.toDouble() / it.denominator }
|
||||
|
@ -768,7 +768,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
|||
if (canReadWithMetadataExtractor(mimeType)) {
|
||||
try {
|
||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||
val metadata = MetadataExtractorHelper.safeRead(input, sizeBytes)
|
||||
val metadata = MetadataExtractorHelper.safeRead(input)
|
||||
val fields = HashMap<Int, Any?>()
|
||||
for (dir in metadata.getDirectoriesOfType(ExifIFD0Directory::class.java)) {
|
||||
if (dir.containsGeoTiffTags()) {
|
||||
|
@ -831,7 +831,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
|||
if (canReadWithMetadataExtractor(mimeType)) {
|
||||
try {
|
||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||
val metadata = MetadataExtractorHelper.safeRead(input, sizeBytes)
|
||||
val metadata = MetadataExtractorHelper.safeRead(input)
|
||||
val fields: FieldMap = hashMapOf(
|
||||
"projectionType" to XMP.GPANO_PROJECTION_TYPE_DEFAULT,
|
||||
)
|
||||
|
@ -895,7 +895,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
|||
if (canReadWithMetadataExtractor(mimeType)) {
|
||||
try {
|
||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||
val metadata = MetadataExtractorHelper.safeRead(input, sizeBytes)
|
||||
val metadata = MetadataExtractorHelper.safeRead(input)
|
||||
val xmpStrings = metadata.getDirectoriesOfType(XmpDirectory::class.java).mapNotNull { XMPMetaFactory.serializeToString(it.xmpMeta, xmpSerializeOptions) }
|
||||
result.success(xmpStrings.toMutableList())
|
||||
return
|
||||
|
@ -1000,7 +1000,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
|||
if (canReadWithMetadataExtractor(mimeType)) {
|
||||
try {
|
||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||
val metadata = MetadataExtractorHelper.safeRead(input, sizeBytes)
|
||||
val metadata = MetadataExtractorHelper.safeRead(input)
|
||||
val tag = when (field) {
|
||||
ExifInterface.TAG_DATETIME -> ExifIFD0Directory.TAG_DATETIME
|
||||
ExifInterface.TAG_DATETIME_DIGITIZED -> ExifSubIFDDirectory.TAG_DATETIME_DIGITIZED
|
||||
|
|
|
@ -48,15 +48,15 @@ object MetadataExtractorHelper {
|
|||
return FileTypeDetector.detectFileType(bufferedInputStream).mimeType
|
||||
}
|
||||
|
||||
fun safeRead(input: InputStream, sizeBytes: Long?): com.drew.metadata.Metadata {
|
||||
val streamLength = sizeBytes ?: -1
|
||||
fun safeRead(input: InputStream): com.drew.metadata.Metadata {
|
||||
val bufferedInputStream = if (input is BufferedInputStream) input else BufferedInputStream(input)
|
||||
val fileType = FileTypeDetector.detectFileType(bufferedInputStream)
|
||||
|
||||
val metadata = if (fileType == FileType.Jpeg) {
|
||||
safeReadJpeg(bufferedInputStream)
|
||||
} else {
|
||||
ImageMetadataReader.readMetadata(bufferedInputStream, streamLength, fileType)
|
||||
// providing the stream length is risky, as it may crash if it is incorrect
|
||||
ImageMetadataReader.readMetadata(bufferedInputStream, -1L, fileType)
|
||||
}
|
||||
|
||||
metadata.addDirectory(FileTypeDirectory(fileType))
|
||||
|
|
|
@ -140,7 +140,7 @@ object MultiPage {
|
|||
fun getMotionPhotoOffset(context: Context, uri: Uri, mimeType: String, sizeBytes: Long): Long? {
|
||||
try {
|
||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||
val metadata = MetadataExtractorHelper.safeRead(input, sizeBytes)
|
||||
val metadata = MetadataExtractorHelper.safeRead(input)
|
||||
for (dir in metadata.getDirectoriesOfType(XmpDirectory::class.java)) {
|
||||
var offsetFromEnd: Long? = null
|
||||
val xmpMeta = dir.xmpMeta
|
||||
|
@ -194,7 +194,7 @@ object MultiPage {
|
|||
return pages
|
||||
}
|
||||
|
||||
fun isMultiPageTiff(context: Context, uri: Uri) = getTiffPageInfo(context, uri, 0)?.outDirectoryCount ?: 1 > 1
|
||||
fun isMultiPageTiff(context: Context, uri: Uri) = (getTiffPageInfo(context, uri, 0)?.outDirectoryCount ?: 1) > 1
|
||||
|
||||
private fun getTiffPageInfo(context: Context, uri: Uri, page: Int): TiffBitmapFactory.Options? {
|
||||
try {
|
||||
|
|
|
@ -97,10 +97,10 @@ class SourceEntry {
|
|||
get() = if (uri.scheme == ContentResolver.SCHEME_CONTENT) uri.tryParseId() else null
|
||||
|
||||
val isSized: Boolean
|
||||
get() = width ?: 0 > 0 && height ?: 0 > 0
|
||||
get() = (width ?: 0) > 0 && (height ?: 0) > 0
|
||||
|
||||
private val hasDuration: Boolean
|
||||
get() = durationMillis ?: 0 > 0
|
||||
get() = (durationMillis ?: 0) > 0
|
||||
|
||||
val isVideo: Boolean
|
||||
get() = MimeTypes.isVideo(sourceMimeType)
|
||||
|
@ -161,7 +161,7 @@ class SourceEntry {
|
|||
|
||||
try {
|
||||
Metadata.openSafeInputStream(context, uri, sourceMimeType, sizeBytes)?.use { input ->
|
||||
val metadata = MetadataExtractorHelper.safeRead(input, sizeBytes)
|
||||
val metadata = MetadataExtractorHelper.safeRead(input)
|
||||
|
||||
// do not switch on specific MIME types, as the reported MIME type could be wrong
|
||||
// (e.g. PNG registered as JPG)
|
||||
|
|
|
@ -84,7 +84,7 @@ object MimeTypes {
|
|||
// as of Flutter v1.22.0, with additional custom handling for SVG
|
||||
fun canDecodeWithFlutter(mimeType: String, rotationDegrees: Int?, isFlipped: Boolean?) = when (mimeType) {
|
||||
JPEG, GIF, WEBP, BMP, WBMP, ICO, SVG -> true
|
||||
PNG -> rotationDegrees ?: 0 == 0 && !(isFlipped ?: false)
|
||||
PNG -> (rotationDegrees ?: 0) == 0 && !(isFlipped ?: false)
|
||||
else -> false
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue